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 
17 /** \file
18  * \ingroup bke
19  */
20 
21 #include "MEM_guardedalloc.h"
22 
23 #include <math.h>
24 #include <stdio.h>
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_kdtree.h"
28 #include "BLI_math.h"
29 #include "BLI_string_utils.h"
30 #include "BLI_task.h"
31 #include "BLI_threads.h"
32 #include "BLI_utildefines.h"
33 
34 #include "BLT_translation.h"
35 
36 #include "DNA_anim_types.h"
37 #include "DNA_armature_types.h"
38 #include "DNA_collection_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_dynamicpaint_types.h"
41 #include "DNA_material_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_modifier_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_texture_types.h"
48 
49 #include "BKE_armature.h"
50 #include "BKE_bvhutils.h" /* bvh tree */
51 #include "BKE_collection.h"
52 #include "BKE_collision.h"
53 #include "BKE_colorband.h"
54 #include "BKE_constraint.h"
55 #include "BKE_customdata.h"
56 #include "BKE_deform.h"
57 #include "BKE_dynamicpaint.h"
58 #include "BKE_effect.h"
59 #include "BKE_image.h"
60 #include "BKE_lib_id.h"
61 #include "BKE_main.h"
62 #include "BKE_material.h"
63 #include "BKE_mesh.h"
64 #include "BKE_mesh_mapping.h"
65 #include "BKE_mesh_runtime.h"
66 #include "BKE_modifier.h"
67 #include "BKE_object.h"
68 #include "BKE_particle.h"
69 #include "BKE_pointcache.h"
70 #include "BKE_scene.h"
71 
72 #include "DEG_depsgraph.h"
73 #include "DEG_depsgraph_query.h"
74 
75 /* for image output */
76 #include "IMB_imbuf.h"
77 #include "IMB_imbuf_types.h"
78 
79 /* to read material/texture color */
80 #include "RE_render_ext.h"
81 #include "RE_shader_ext.h"
82 
83 #include "atomic_ops.h"
84 
85 #include "CLG_log.h"
86 
87 /* could enable at some point but for now there are far too many conversions */
88 #ifdef __GNUC__
89 //#  pragma GCC diagnostic ignored "-Wdouble-promotion"
90 #endif
91 
92 static CLG_LogRef LOG = {"bke.dynamicpaint"};
93 
94 /* precalculated gaussian factors for 5x super sampling */
95 static const float gaussianFactors[5] = {
96     0.996849f,
97     0.596145f,
98     0.596145f,
99     0.596145f,
100     0.524141f,
101 };
102 static const float gaussianTotal = 3.309425f;
103 
104 /* UV Image neighboring pixel table x and y list */
105 static int neighX[8] = {1, 1, 0, -1, -1, -1, 0, 1};
106 static int neighY[8] = {0, 1, 1, 1, 0, -1, -1, -1};
107 
108 /* Neighbor x/y list that prioritizes grid directions over diagonals */
109 static int neighStraightX[8] = {1, 0, -1, 0, 1, -1, -1, 1};
110 static int neighStraightY[8] = {0, 1, 0, -1, 1, 1, -1, -1};
111 
112 /* subframe_updateObject() flags */
113 #define SUBFRAME_RECURSION 5
114 /* surface_getBrushFlags() return vals */
115 #define BRUSH_USES_VELOCITY (1 << 0)
116 /* brush mesh raycast status */
117 #define HIT_VOLUME 1
118 #define HIT_PROXIMITY 2
119 /* dynamicPaint_findNeighborPixel() return codes */
120 #define NOT_FOUND -1
121 #define ON_MESH_EDGE -2
122 #define OUT_OF_TEXTURE -3
123 /* paint effect default movement per frame in global units */
124 #define EFF_MOVEMENT_PER_FRAME 0.05f
125 /* initial wave time factor */
126 #define WAVE_TIME_FAC (1.0f / 24.f)
127 #define CANVAS_REL_SIZE 5.0f
128 /* drying limits */
129 #define MIN_WETNESS 0.001f
130 #define MAX_WETNESS 5.0f
131 
132 /* dissolve inline function */
value_dissolve(float * r_value,const float time,const float scale,const bool is_log)133 BLI_INLINE void value_dissolve(float *r_value,
134                                const float time,
135                                const float scale,
136                                const bool is_log)
137 {
138   *r_value = (is_log) ? (*r_value) * (powf(MIN_WETNESS, 1.0f / (1.2f * time / scale))) :
139                         (*r_value) - 1.0f / time * scale;
140 }
141 
142 /***************************** Internal Structs ***************************/
143 
144 typedef struct Bounds2D {
145   float min[2], max[2];
146 } Bounds2D;
147 
148 typedef struct Bounds3D {
149   float min[3], max[3];
150   bool valid;
151 } Bounds3D;
152 
153 typedef struct VolumeGrid {
154   int dim[3];
155   /** whole grid bounds */
156   Bounds3D grid_bounds;
157 
158   /** (x*y*z) precalculated grid cell bounds */
159   Bounds3D *bounds;
160   /** (x*y*z) t_index begin id */
161   int *s_pos;
162   /** (x*y*z) number of t_index points */
163   int *s_num;
164   /** actual surface point index, access: (s_pos + s_num) */
165   int *t_index;
166 
167   int *temp_t_index;
168 } VolumeGrid;
169 
170 typedef struct Vec3f {
171   float v[3];
172 } Vec3f;
173 
174 typedef struct BakeAdjPoint {
175   /** vector pointing towards this neighbor */
176   float dir[3];
177   /** distance to */
178   float dist;
179 } BakeAdjPoint;
180 
181 /** Surface data used while processing a frame */
182 typedef struct PaintBakeNormal {
183   /** current pixel world-space inverted normal */
184   float invNorm[3];
185   /** normal directional scale for displace mapping */
186   float normal_scale;
187 } PaintBakeNormal;
188 
189 /** Temp surface data used to process a frame */
190 typedef struct PaintBakeData {
191   /* point space data */
192   PaintBakeNormal *bNormal;
193   /** index to start reading point sample realCoord */
194   int *s_pos;
195   /** num of realCoord samples */
196   int *s_num;
197   /** current pixel center world-space coordinates for each sample ordered as (s_pos + s_num) */
198   Vec3f *realCoord;
199   Bounds3D mesh_bounds;
200   float dim[3];
201 
202   /* adjacency info */
203   /** current global neighbor distances and directions, if required */
204   BakeAdjPoint *bNeighs;
205   double average_dist;
206   /* space partitioning */
207   /** space partitioning grid to optimize brush checks */
208   VolumeGrid *grid;
209 
210   /* velocity and movement */
211   /** speed vector in global space movement per frame, if required */
212   Vec3f *velocity;
213   Vec3f *prev_velocity;
214   /** special temp data for post-p velocity based brushes like smudge
215    * 3 float dir vec + 1 float str */
216   float *brush_velocity;
217   /** copy of previous frame vertices. used to observe surface movement. */
218   MVert *prev_verts;
219   /** Previous frame object matrix. */
220   float prev_obmat[4][4];
221   /** flag to check if surface was cleared/reset -> have to redo velocity etc. */
222   int clear;
223 } PaintBakeData;
224 
225 /** UV Image sequence format point */
226 typedef struct PaintUVPoint {
227   /* Pixel / mesh data */
228   /** tri index on domain derived mesh */
229   unsigned int tri_index;
230   unsigned int pixel_index;
231   /* vertex indexes */
232   unsigned int v1, v2, v3;
233 
234   /** If this pixel isn't uv mapped to any face, but its neighboring pixel is. */
235   unsigned int neighbor_pixel;
236 } PaintUVPoint;
237 
238 typedef struct ImgSeqFormatData {
239   PaintUVPoint *uv_p;
240   Vec3f *barycentricWeights; /* b-weights for all pixel samples */
241 } ImgSeqFormatData;
242 
243 /* adjacency data flags */
244 #define ADJ_ON_MESH_EDGE (1 << 0)
245 #define ADJ_BORDER_PIXEL (1 << 1)
246 
247 typedef struct PaintAdjData {
248   /** Array of neighboring point indexes, for single sample use (n_index + neigh_num). */
249   int *n_target;
250   /** Index to start reading n_target for each point. */
251   int *n_index;
252   /** Num of neighs for each point. */
253   int *n_num;
254   /** Vertex adjacency flags. */
255   int *flags;
256   /** Size of n_target. */
257   int total_targets;
258   /** Indices of border pixels (only for texture paint). */
259   int *border;
260   /** Size of border. */
261   int total_border;
262 } PaintAdjData;
263 
264 /************************* Runtime evaluation store ***************************/
265 
dynamicPaint_Modifier_free_runtime(DynamicPaintRuntime * runtime_data)266 void dynamicPaint_Modifier_free_runtime(DynamicPaintRuntime *runtime_data)
267 {
268   if (runtime_data == NULL) {
269     return;
270   }
271   if (runtime_data->canvas_mesh) {
272     BKE_id_free(NULL, runtime_data->canvas_mesh);
273   }
274   if (runtime_data->brush_mesh) {
275     BKE_id_free(NULL, runtime_data->brush_mesh);
276   }
277   MEM_freeN(runtime_data);
278 }
279 
dynamicPaint_Modifier_runtime_ensure(DynamicPaintModifierData * pmd)280 static DynamicPaintRuntime *dynamicPaint_Modifier_runtime_ensure(DynamicPaintModifierData *pmd)
281 {
282   if (pmd->modifier.runtime == NULL) {
283     pmd->modifier.runtime = MEM_callocN(sizeof(DynamicPaintRuntime), "dynamic paint runtime");
284   }
285   return (DynamicPaintRuntime *)pmd->modifier.runtime;
286 }
287 
dynamicPaint_canvas_mesh_get(DynamicPaintCanvasSettings * canvas)288 static Mesh *dynamicPaint_canvas_mesh_get(DynamicPaintCanvasSettings *canvas)
289 {
290   if (canvas->pmd->modifier.runtime == NULL) {
291     return NULL;
292   }
293   DynamicPaintRuntime *runtime_data = (DynamicPaintRuntime *)canvas->pmd->modifier.runtime;
294   return runtime_data->canvas_mesh;
295 }
296 
dynamicPaint_brush_mesh_get(DynamicPaintBrushSettings * brush)297 static Mesh *dynamicPaint_brush_mesh_get(DynamicPaintBrushSettings *brush)
298 {
299   if (brush->pmd->modifier.runtime == NULL) {
300     return NULL;
301   }
302   DynamicPaintRuntime *runtime_data = (DynamicPaintRuntime *)brush->pmd->modifier.runtime;
303   return runtime_data->brush_mesh;
304 }
305 
306 /***************************** General Utils ******************************/
307 
308 /* Set canvas error string to display at the bake report */
setError(DynamicPaintCanvasSettings * canvas,const char * string)309 static bool setError(DynamicPaintCanvasSettings *canvas, const char *string)
310 {
311   /* Add error to canvas ui info label */
312   BLI_strncpy(canvas->error, string, sizeof(canvas->error));
313   CLOG_STR_ERROR(&LOG, string);
314   return false;
315 }
316 
317 /* Get number of surface points for cached types */
dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface * surface)318 static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface)
319 {
320   if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) {
321     return 0; /* not supported atm */
322   }
323   if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
324     const Mesh *canvas_mesh = dynamicPaint_canvas_mesh_get(surface->canvas);
325     return (canvas_mesh) ? canvas_mesh->totvert : 0;
326   }
327 
328   return 0;
329 }
330 
331 /* get currently active surface (in user interface) */
get_activeSurface(DynamicPaintCanvasSettings * canvas)332 DynamicPaintSurface *get_activeSurface(DynamicPaintCanvasSettings *canvas)
333 {
334   return BLI_findlink(&canvas->surfaces, canvas->active_sur);
335 }
336 
dynamicPaint_outputLayerExists(struct DynamicPaintSurface * surface,Object * ob,int output)337 bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object *ob, int output)
338 {
339   const char *name;
340 
341   if (output == 0) {
342     name = surface->output_name;
343   }
344   else if (output == 1) {
345     name = surface->output_name2;
346   }
347   else {
348     return false;
349   }
350 
351   if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
352     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
353       Mesh *me = ob->data;
354       return (CustomData_get_named_layer_index(&me->ldata, CD_MLOOPCOL, name) != -1);
355     }
356     if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
357       return (BKE_object_defgroup_name_index(ob, name) != -1);
358     }
359   }
360 
361   return false;
362 }
363 
surface_duplicateOutputExists(void * arg,const char * name)364 static bool surface_duplicateOutputExists(void *arg, const char *name)
365 {
366   DynamicPaintSurface *t_surface = arg;
367   DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
368 
369   for (; surface; surface = surface->next) {
370     if (surface != t_surface && surface->type == t_surface->type &&
371         surface->format == t_surface->format) {
372       if ((surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) ||
373           (surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2))) {
374         return true;
375       }
376     }
377   }
378   return false;
379 }
380 
surface_setUniqueOutputName(DynamicPaintSurface * surface,char * basename,int output)381 static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output)
382 {
383   char name[64];
384   BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */
385   if (output == 0) {
386     BLI_uniquename_cb(surface_duplicateOutputExists,
387                       surface,
388                       name,
389                       '.',
390                       surface->output_name,
391                       sizeof(surface->output_name));
392   }
393   else if (output == 1) {
394     BLI_uniquename_cb(surface_duplicateOutputExists,
395                       surface,
396                       name,
397                       '.',
398                       surface->output_name2,
399                       sizeof(surface->output_name2));
400   }
401 }
402 
surface_duplicateNameExists(void * arg,const char * name)403 static bool surface_duplicateNameExists(void *arg, const char *name)
404 {
405   DynamicPaintSurface *t_surface = arg;
406   DynamicPaintSurface *surface = t_surface->canvas->surfaces.first;
407 
408   for (; surface; surface = surface->next) {
409     if (surface != t_surface && STREQ(name, surface->name)) {
410       return true;
411     }
412   }
413   return false;
414 }
415 
dynamicPaintSurface_setUniqueName(DynamicPaintSurface * surface,const char * basename)416 void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename)
417 {
418   char name[64];
419   BLI_strncpy(name, basename, sizeof(name)); /* in case basename is surface->name use a copy */
420   BLI_uniquename_cb(
421       surface_duplicateNameExists, surface, name, '.', surface->name, sizeof(surface->name));
422 }
423 
424 /* change surface data to defaults on new type */
dynamicPaintSurface_updateType(struct DynamicPaintSurface * surface)425 void dynamicPaintSurface_updateType(struct DynamicPaintSurface *surface)
426 {
427   if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
428     surface->output_name[0] = '\0';
429     surface->output_name2[0] = '\0';
430     surface->flags |= MOD_DPAINT_ANTIALIAS;
431     surface->depth_clamp = 1.0f;
432   }
433   else {
434     strcpy(surface->output_name, "dp_");
435     BLI_strncpy(surface->output_name2, surface->output_name, sizeof(surface->output_name2));
436     surface->flags &= ~MOD_DPAINT_ANTIALIAS;
437     surface->depth_clamp = 0.0f;
438   }
439 
440   if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
441     strcat(surface->output_name, "paintmap");
442     strcat(surface->output_name2, "wetmap");
443     surface_setUniqueOutputName(surface, surface->output_name2, 1);
444   }
445   else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
446     strcat(surface->output_name, "displace");
447   }
448   else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
449     strcat(surface->output_name, "weight");
450   }
451   else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
452     strcat(surface->output_name, "wave");
453   }
454 
455   surface_setUniqueOutputName(surface, surface->output_name, 0);
456 }
457 
surface_totalSamples(DynamicPaintSurface * surface)458 static int surface_totalSamples(DynamicPaintSurface *surface)
459 {
460   if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->flags & MOD_DPAINT_ANTIALIAS) {
461     return (surface->data->total_points * 5);
462   }
463   if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX && surface->flags & MOD_DPAINT_ANTIALIAS &&
464       surface->data->adj_data) {
465     return (surface->data->total_points + surface->data->adj_data->total_targets);
466   }
467 
468   return surface->data->total_points;
469 }
470 
blendColors(const float t_color[3],const float t_alpha,const float s_color[3],const float s_alpha,float result[4])471 static void blendColors(const float t_color[3],
472                         const float t_alpha,
473                         const float s_color[3],
474                         const float s_alpha,
475                         float result[4])
476 {
477   /* Same thing as BLI's blend_color_mix_float(), but for non-premultiplied alpha. */
478   float i_alpha = 1.0f - s_alpha;
479   float f_alpha = t_alpha * i_alpha + s_alpha;
480 
481   /* blend colors */
482   if (f_alpha) {
483     for (int i = 0; i < 3; i++) {
484       result[i] = (t_color[i] * t_alpha * i_alpha + s_color[i] * s_alpha) / f_alpha;
485     }
486   }
487   else {
488     copy_v3_v3(result, t_color);
489   }
490   /* return final alpha */
491   result[3] = f_alpha;
492 }
493 
494 /* Mix two alpha weighed colors by a defined ratio. output is saved at a_color */
mixColors(float a_color[3],float a_weight,const float b_color[3],float b_weight,float ratio)495 static float mixColors(
496     float a_color[3], float a_weight, const float b_color[3], float b_weight, float ratio)
497 {
498   float weight_ratio, factor;
499   if (b_weight) {
500     /* if first value has no weight just use b_color */
501     if (!a_weight) {
502       copy_v3_v3(a_color, b_color);
503       return b_weight * ratio;
504     }
505     weight_ratio = b_weight / (a_weight + b_weight);
506   }
507   else {
508     return a_weight * (1.0f - ratio);
509   }
510 
511   /* calculate final interpolation factor */
512   if (ratio <= 0.5f) {
513     factor = weight_ratio * (ratio * 2.0f);
514   }
515   else {
516     ratio = (ratio * 2.0f - 1.0f);
517     factor = weight_ratio * (1.0f - ratio) + ratio;
518   }
519   /* mix final color */
520   interp_v3_v3v3(a_color, a_color, b_color, factor);
521   return (1.0f - factor) * a_weight + factor * b_weight;
522 }
523 
scene_setSubframe(Scene * scene,float subframe)524 static void scene_setSubframe(Scene *scene, float subframe)
525 {
526   /* dynamic paint subframes must be done on previous frame */
527   scene->r.cfra -= 1;
528   scene->r.subframe = subframe;
529 }
530 
surface_getBrushFlags(DynamicPaintSurface * surface,Depsgraph * depsgraph)531 static int surface_getBrushFlags(DynamicPaintSurface *surface, Depsgraph *depsgraph)
532 {
533   unsigned int numobjects;
534   Object **objects = BKE_collision_objects_create(
535       depsgraph, NULL, surface->brush_group, &numobjects, eModifierType_DynamicPaint);
536 
537   int flags = 0;
538 
539   for (int i = 0; i < numobjects; i++) {
540     Object *brushObj = objects[i];
541 
542     ModifierData *md = BKE_modifiers_findby_type(brushObj, eModifierType_DynamicPaint);
543     if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) {
544       DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
545 
546       if (pmd2->brush) {
547         DynamicPaintBrushSettings *brush = pmd2->brush;
548 
549         if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
550           flags |= BRUSH_USES_VELOCITY;
551         }
552       }
553     }
554   }
555 
556   BKE_collision_objects_free(objects);
557 
558   return flags;
559 }
560 
561 /* check whether two bounds intersect */
boundsIntersect(Bounds3D * b1,Bounds3D * b2)562 static bool boundsIntersect(Bounds3D *b1, Bounds3D *b2)
563 {
564   if (!b1->valid || !b2->valid) {
565     return false;
566   }
567   for (int i = 2; i--;) {
568     if (!(b1->min[i] <= b2->max[i] && b1->max[i] >= b2->min[i])) {
569       return false;
570     }
571   }
572   return true;
573 }
574 
575 /* check whether two bounds intersect inside defined proximity */
boundsIntersectDist(Bounds3D * b1,Bounds3D * b2,const float dist)576 static bool boundsIntersectDist(Bounds3D *b1, Bounds3D *b2, const float dist)
577 {
578   if (!b1->valid || !b2->valid) {
579     return false;
580   }
581   for (int i = 2; i--;) {
582     if (!(b1->min[i] <= (b2->max[i] + dist) && b1->max[i] >= (b2->min[i] - dist))) {
583       return false;
584     }
585   }
586   return true;
587 }
588 
589 /* check whether bounds intersects a point with given radius */
boundIntersectPoint(Bounds3D * b,const float point[3],const float radius)590 static bool boundIntersectPoint(Bounds3D *b, const float point[3], const float radius)
591 {
592   if (!b->valid) {
593     return false;
594   }
595   for (int i = 2; i--;) {
596     if (!(b->min[i] <= (point[i] + radius) && b->max[i] >= (point[i] - radius))) {
597       return false;
598     }
599   }
600   return true;
601 }
602 
603 /* expand bounds by a new point */
boundInsert(Bounds3D * b,const float point[3])604 static void boundInsert(Bounds3D *b, const float point[3])
605 {
606   if (!b->valid) {
607     copy_v3_v3(b->min, point);
608     copy_v3_v3(b->max, point);
609     b->valid = true;
610     return;
611   }
612 
613   minmax_v3v3_v3(b->min, b->max, point);
614 }
615 
getSurfaceDimension(PaintSurfaceData * sData)616 static float getSurfaceDimension(PaintSurfaceData *sData)
617 {
618   Bounds3D *mb = &sData->bData->mesh_bounds;
619   return max_fff((mb->max[0] - mb->min[0]), (mb->max[1] - mb->min[1]), (mb->max[2] - mb->min[2]));
620 }
621 
freeGrid(PaintSurfaceData * data)622 static void freeGrid(PaintSurfaceData *data)
623 {
624   PaintBakeData *bData = data->bData;
625   VolumeGrid *grid = bData->grid;
626 
627   if (grid->bounds) {
628     MEM_freeN(grid->bounds);
629   }
630   if (grid->s_pos) {
631     MEM_freeN(grid->s_pos);
632   }
633   if (grid->s_num) {
634     MEM_freeN(grid->s_num);
635   }
636   if (grid->t_index) {
637     MEM_freeN(grid->t_index);
638   }
639 
640   MEM_freeN(bData->grid);
641   bData->grid = NULL;
642 }
643 
grid_bound_insert_cb_ex(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict tls)644 static void grid_bound_insert_cb_ex(void *__restrict userdata,
645                                     const int i,
646                                     const TaskParallelTLS *__restrict tls)
647 {
648   PaintBakeData *bData = userdata;
649 
650   Bounds3D *grid_bound = tls->userdata_chunk;
651 
652   boundInsert(grid_bound, bData->realCoord[bData->s_pos[i]].v);
653 }
654 
grid_bound_insert_reduce(const void * __restrict UNUSED (userdata),void * __restrict chunk_join,void * __restrict chunk)655 static void grid_bound_insert_reduce(const void *__restrict UNUSED(userdata),
656                                      void *__restrict chunk_join,
657                                      void *__restrict chunk)
658 {
659   Bounds3D *join = chunk_join;
660   Bounds3D *grid_bound = chunk;
661 
662   boundInsert(join, grid_bound->min);
663   boundInsert(join, grid_bound->max);
664 }
665 
grid_cell_points_cb_ex(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict tls)666 static void grid_cell_points_cb_ex(void *__restrict userdata,
667                                    const int i,
668                                    const TaskParallelTLS *__restrict tls)
669 {
670   PaintBakeData *bData = userdata;
671   VolumeGrid *grid = bData->grid;
672   int *temp_t_index = grid->temp_t_index;
673   int *s_num = tls->userdata_chunk;
674 
675   int co[3];
676 
677   for (int j = 3; j--;) {
678     co[j] = (int)floorf((bData->realCoord[bData->s_pos[i]].v[j] - grid->grid_bounds.min[j]) /
679                         bData->dim[j] * grid->dim[j]);
680     CLAMP(co[j], 0, grid->dim[j] - 1);
681   }
682 
683   temp_t_index[i] = co[0] + co[1] * grid->dim[0] + co[2] * grid->dim[0] * grid->dim[1];
684   s_num[temp_t_index[i]]++;
685 }
686 
grid_cell_points_reduce(const void * __restrict userdata,void * __restrict chunk_join,void * __restrict chunk)687 static void grid_cell_points_reduce(const void *__restrict userdata,
688                                     void *__restrict chunk_join,
689                                     void *__restrict chunk)
690 {
691   const PaintBakeData *bData = userdata;
692   const VolumeGrid *grid = bData->grid;
693   const int grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
694 
695   int *join_s_num = chunk_join;
696   int *s_num = chunk;
697 
698   /* calculate grid indexes */
699   for (int i = 0; i < grid_cells; i++) {
700     join_s_num[i] += s_num[i];
701   }
702 }
703 
grid_cell_bounds_cb(void * __restrict userdata,const int x,const TaskParallelTLS * __restrict UNUSED (tls))704 static void grid_cell_bounds_cb(void *__restrict userdata,
705                                 const int x,
706                                 const TaskParallelTLS *__restrict UNUSED(tls))
707 {
708   PaintBakeData *bData = userdata;
709   VolumeGrid *grid = bData->grid;
710   float *dim = bData->dim;
711   int *grid_dim = grid->dim;
712 
713   for (int y = 0; y < grid_dim[1]; y++) {
714     for (int z = 0; z < grid_dim[2]; z++) {
715       const int b_index = x + y * grid_dim[0] + z * grid_dim[0] * grid_dim[1];
716       /* set bounds */
717       for (int j = 3; j--;) {
718         const int s = (j == 0) ? x : ((j == 1) ? y : z);
719         grid->bounds[b_index].min[j] = grid->grid_bounds.min[j] + dim[j] / grid_dim[j] * s;
720         grid->bounds[b_index].max[j] = grid->grid_bounds.min[j] + dim[j] / grid_dim[j] * (s + 1);
721       }
722       grid->bounds[b_index].valid = true;
723     }
724   }
725 }
726 
surfaceGenerateGrid(struct DynamicPaintSurface * surface)727 static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
728 {
729   PaintSurfaceData *sData = surface->data;
730   PaintBakeData *bData = sData->bData;
731   VolumeGrid *grid;
732   int grid_cells, axis = 3;
733   int *temp_t_index = NULL;
734   int *temp_s_num = NULL;
735 
736   if (bData->grid) {
737     freeGrid(sData);
738   }
739 
740   bData->grid = MEM_callocN(sizeof(VolumeGrid), "Surface Grid");
741   grid = bData->grid;
742 
743   {
744     int i, error = 0;
745     float dim_factor, volume, dim[3];
746     float td[3];
747     float min_dim;
748 
749     /* calculate canvas dimensions */
750     /* Important to init correctly our ref grid_bound... */
751     boundInsert(&grid->grid_bounds, bData->realCoord[bData->s_pos[0]].v);
752     {
753       TaskParallelSettings settings;
754       BLI_parallel_range_settings_defaults(&settings);
755       settings.use_threading = (sData->total_points > 1000);
756       settings.userdata_chunk = &grid->grid_bounds;
757       settings.userdata_chunk_size = sizeof(grid->grid_bounds);
758       settings.func_reduce = grid_bound_insert_reduce;
759       BLI_task_parallel_range(0, sData->total_points, bData, grid_bound_insert_cb_ex, &settings);
760     }
761     /* get dimensions */
762     sub_v3_v3v3(dim, grid->grid_bounds.max, grid->grid_bounds.min);
763     copy_v3_v3(td, dim);
764     copy_v3_v3(bData->dim, dim);
765     min_dim = max_fff(td[0], td[1], td[2]) / 1000.f;
766 
767     /* deactivate zero axises */
768     for (i = 0; i < 3; i++) {
769       if (td[i] < min_dim) {
770         td[i] = 1.0f;
771         axis--;
772       }
773     }
774 
775     if (axis == 0 || max_fff(td[0], td[1], td[2]) < 0.0001f) {
776       MEM_freeN(bData->grid);
777       bData->grid = NULL;
778       return;
779     }
780 
781     /* now calculate grid volume/area/width depending on num of active axis */
782     volume = td[0] * td[1] * td[2];
783 
784     /* determine final grid size by trying to fit average 10.000 points per grid cell */
785     dim_factor = (float)pow((double)volume / ((double)sData->total_points / 10000.0),
786                             1.0 / (double)axis);
787 
788     /* define final grid size using dim_factor, use min 3 for active axises */
789     for (i = 0; i < 3; i++) {
790       grid->dim[i] = (int)floor(td[i] / dim_factor);
791       CLAMP(grid->dim[i], (dim[i] >= min_dim) ? 3 : 1, 100);
792     }
793     grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
794 
795     /* allocate memory for grids */
796     grid->bounds = MEM_callocN(sizeof(Bounds3D) * grid_cells, "Surface Grid Bounds");
797     grid->s_pos = MEM_callocN(sizeof(int) * grid_cells, "Surface Grid Position");
798 
799     grid->s_num = MEM_callocN(sizeof(int) * grid_cells, "Surface Grid Points");
800     temp_s_num = MEM_callocN(sizeof(int) * grid_cells, "Temp Surface Grid Points");
801     grid->t_index = MEM_callocN(sizeof(int) * sData->total_points, "Surface Grid Target Ids");
802     grid->temp_t_index = temp_t_index = MEM_callocN(sizeof(int) * sData->total_points,
803                                                     "Temp Surface Grid Target Ids");
804 
805     /* in case of an allocation failure abort here */
806     if (!grid->bounds || !grid->s_pos || !grid->s_num || !grid->t_index || !temp_s_num ||
807         !temp_t_index) {
808       error = 1;
809     }
810 
811     if (!error) {
812       /* calculate number of points within each cell */
813       {
814         TaskParallelSettings settings;
815         BLI_parallel_range_settings_defaults(&settings);
816         settings.use_threading = (sData->total_points > 1000);
817         settings.userdata_chunk = grid->s_num;
818         settings.userdata_chunk_size = sizeof(*grid->s_num) * grid_cells;
819         settings.func_reduce = grid_cell_points_reduce;
820         BLI_task_parallel_range(0, sData->total_points, bData, grid_cell_points_cb_ex, &settings);
821       }
822 
823       /* calculate grid indexes (not needed for first cell, which is zero). */
824       for (i = 1; i < grid_cells; i++) {
825         grid->s_pos[i] = grid->s_pos[i - 1] + grid->s_num[i - 1];
826       }
827 
828       /* save point indexes to final array */
829       for (i = 0; i < sData->total_points; i++) {
830         int pos = grid->s_pos[temp_t_index[i]] + temp_s_num[temp_t_index[i]];
831         grid->t_index[pos] = i;
832 
833         temp_s_num[temp_t_index[i]]++;
834       }
835 
836       /* calculate cell bounds */
837       {
838         TaskParallelSettings settings;
839         BLI_parallel_range_settings_defaults(&settings);
840         settings.use_threading = (grid_cells > 1000);
841         BLI_task_parallel_range(0, grid->dim[0], bData, grid_cell_bounds_cb, &settings);
842       }
843     }
844 
845     if (temp_s_num) {
846       MEM_freeN(temp_s_num);
847     }
848     if (temp_t_index) {
849       MEM_freeN(temp_t_index);
850     }
851     grid->temp_t_index = NULL;
852 
853     if (error || !grid->s_num) {
854       setError(surface->canvas, N_("Not enough free memory"));
855       freeGrid(sData);
856     }
857   }
858 }
859 
860 /***************************** Freeing data ******************************/
861 
862 /* Free brush data */
dynamicPaint_freeBrush(struct DynamicPaintModifierData * pmd)863 void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
864 {
865   if (pmd->brush) {
866     if (pmd->brush->paint_ramp) {
867       MEM_freeN(pmd->brush->paint_ramp);
868     }
869     if (pmd->brush->vel_ramp) {
870       MEM_freeN(pmd->brush->vel_ramp);
871     }
872 
873     MEM_freeN(pmd->brush);
874     pmd->brush = NULL;
875   }
876 }
877 
dynamicPaint_freeAdjData(PaintSurfaceData * data)878 static void dynamicPaint_freeAdjData(PaintSurfaceData *data)
879 {
880   if (data->adj_data) {
881     if (data->adj_data->n_index) {
882       MEM_freeN(data->adj_data->n_index);
883     }
884     if (data->adj_data->n_num) {
885       MEM_freeN(data->adj_data->n_num);
886     }
887     if (data->adj_data->n_target) {
888       MEM_freeN(data->adj_data->n_target);
889     }
890     if (data->adj_data->flags) {
891       MEM_freeN(data->adj_data->flags);
892     }
893     if (data->adj_data->border) {
894       MEM_freeN(data->adj_data->border);
895     }
896     MEM_freeN(data->adj_data);
897     data->adj_data = NULL;
898   }
899 }
900 
free_bakeData(PaintSurfaceData * data)901 static void free_bakeData(PaintSurfaceData *data)
902 {
903   PaintBakeData *bData = data->bData;
904   if (bData) {
905     if (bData->bNormal) {
906       MEM_freeN(bData->bNormal);
907     }
908     if (bData->s_pos) {
909       MEM_freeN(bData->s_pos);
910     }
911     if (bData->s_num) {
912       MEM_freeN(bData->s_num);
913     }
914     if (bData->realCoord) {
915       MEM_freeN(bData->realCoord);
916     }
917     if (bData->bNeighs) {
918       MEM_freeN(bData->bNeighs);
919     }
920     if (bData->grid) {
921       freeGrid(data);
922     }
923     if (bData->prev_verts) {
924       MEM_freeN(bData->prev_verts);
925     }
926     if (bData->velocity) {
927       MEM_freeN(bData->velocity);
928     }
929     if (bData->prev_velocity) {
930       MEM_freeN(bData->prev_velocity);
931     }
932 
933     MEM_freeN(data->bData);
934     data->bData = NULL;
935   }
936 }
937 
938 /* free surface data if it's not used anymore */
surface_freeUnusedData(DynamicPaintSurface * surface)939 static void surface_freeUnusedData(DynamicPaintSurface *surface)
940 {
941   if (!surface->data) {
942     return;
943   }
944 
945   /* free bakedata if not active or surface is baked */
946   if (!(surface->flags & MOD_DPAINT_ACTIVE) ||
947       (surface->pointcache && surface->pointcache->flag & PTCACHE_BAKED)) {
948     free_bakeData(surface->data);
949   }
950 }
951 
dynamicPaint_freeSurfaceData(DynamicPaintSurface * surface)952 void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface)
953 {
954   PaintSurfaceData *data = surface->data;
955   if (!data) {
956     return;
957   }
958 
959   if (data->format_data) {
960     /* format specific free */
961     if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
962       ImgSeqFormatData *format_data = (ImgSeqFormatData *)data->format_data;
963       if (format_data->uv_p) {
964         MEM_freeN(format_data->uv_p);
965       }
966       if (format_data->barycentricWeights) {
967         MEM_freeN(format_data->barycentricWeights);
968       }
969     }
970     MEM_freeN(data->format_data);
971   }
972   /* type data */
973   if (data->type_data) {
974     MEM_freeN(data->type_data);
975   }
976   dynamicPaint_freeAdjData(data);
977   /* bake data */
978   free_bakeData(data);
979 
980   MEM_freeN(surface->data);
981   surface->data = NULL;
982 }
983 
dynamicPaint_freeSurface(const DynamicPaintModifierData * pmd,DynamicPaintSurface * surface)984 void dynamicPaint_freeSurface(const DynamicPaintModifierData *pmd, DynamicPaintSurface *surface)
985 {
986   /* point cache */
987   if ((pmd->modifier.flag & eModifierFlag_SharedCaches) == 0) {
988     BKE_ptcache_free_list(&(surface->ptcaches));
989   }
990   surface->pointcache = NULL;
991 
992   if (surface->effector_weights) {
993     MEM_freeN(surface->effector_weights);
994   }
995   surface->effector_weights = NULL;
996 
997   BLI_remlink(&(surface->canvas->surfaces), surface);
998   dynamicPaint_freeSurfaceData(surface);
999   MEM_freeN(surface);
1000 }
1001 
1002 /* Free canvas data */
dynamicPaint_freeCanvas(DynamicPaintModifierData * pmd)1003 void dynamicPaint_freeCanvas(DynamicPaintModifierData *pmd)
1004 {
1005   if (pmd->canvas) {
1006     /* Free surface data */
1007     DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
1008     DynamicPaintSurface *next_surface = NULL;
1009 
1010     while (surface) {
1011       next_surface = surface->next;
1012       dynamicPaint_freeSurface(pmd, surface);
1013       surface = next_surface;
1014     }
1015 
1016     MEM_freeN(pmd->canvas);
1017     pmd->canvas = NULL;
1018   }
1019 }
1020 
1021 /* Free whole dp modifier */
dynamicPaint_Modifier_free(DynamicPaintModifierData * pmd)1022 void dynamicPaint_Modifier_free(DynamicPaintModifierData *pmd)
1023 {
1024   if (pmd == NULL) {
1025     return;
1026   }
1027   dynamicPaint_freeCanvas(pmd);
1028   dynamicPaint_freeBrush(pmd);
1029   dynamicPaint_Modifier_free_runtime(pmd->modifier.runtime);
1030 }
1031 
1032 /***************************** Initialize and reset ******************************/
1033 
1034 /*
1035  * Creates a new surface and adds it to the list
1036  * If scene is null, frame range of 1-250 is used
1037  * A pointer to this surface is returned
1038  */
dynamicPaint_createNewSurface(DynamicPaintCanvasSettings * canvas,Scene * scene)1039 DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *canvas,
1040                                                    Scene *scene)
1041 {
1042   DynamicPaintSurface *surface = MEM_callocN(sizeof(DynamicPaintSurface), "DynamicPaintSurface");
1043   if (!surface) {
1044     return NULL;
1045   }
1046 
1047   surface->canvas = canvas;
1048   surface->format = MOD_DPAINT_SURFACE_F_VERTEX;
1049   surface->type = MOD_DPAINT_SURFACE_T_PAINT;
1050 
1051   /* cache */
1052   surface->pointcache = BKE_ptcache_add(&(surface->ptcaches));
1053   surface->pointcache->flag |= PTCACHE_DISK_CACHE;
1054   surface->pointcache->step = 1;
1055 
1056   /* Set initial values */
1057   surface->flags = MOD_DPAINT_ANTIALIAS | MOD_DPAINT_MULALPHA | MOD_DPAINT_DRY_LOG |
1058                    MOD_DPAINT_DISSOLVE_LOG | MOD_DPAINT_ACTIVE | MOD_DPAINT_OUT1 |
1059                    MOD_DPAINT_USE_DRYING;
1060   surface->effect = 0;
1061   surface->effect_ui = 1;
1062 
1063   surface->diss_speed = 250;
1064   surface->dry_speed = 500;
1065   surface->color_dry_threshold = 1.0f;
1066   surface->depth_clamp = 0.0f;
1067   surface->disp_factor = 1.0f;
1068   surface->disp_type = MOD_DPAINT_DISP_DISPLACE;
1069   surface->image_fileformat = MOD_DPAINT_IMGFORMAT_PNG;
1070 
1071   surface->influence_scale = 1.0f;
1072   surface->radius_scale = 1.0f;
1073 
1074   surface->init_color[0] = 1.0f;
1075   surface->init_color[1] = 1.0f;
1076   surface->init_color[2] = 1.0f;
1077   surface->init_color[3] = 1.0f;
1078 
1079   surface->image_resolution = 256;
1080   surface->substeps = 0;
1081 
1082   if (scene) {
1083     surface->start_frame = scene->r.sfra;
1084     surface->end_frame = scene->r.efra;
1085   }
1086   else {
1087     surface->start_frame = 1;
1088     surface->end_frame = 250;
1089   }
1090 
1091   surface->spread_speed = 1.0f;
1092   surface->color_spread_speed = 1.0f;
1093   surface->shrink_speed = 1.0f;
1094 
1095   surface->wave_damping = 0.04f;
1096   surface->wave_speed = 1.0f;
1097   surface->wave_timescale = 1.0f;
1098   surface->wave_spring = 0.20f;
1099   surface->wave_smoothness = 1.0f;
1100 
1101   BKE_modifier_path_init(
1102       surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint");
1103 
1104   /* Using ID_BRUSH i18n context, as we have no physics/dpaint one for now... */
1105   dynamicPaintSurface_setUniqueName(surface, CTX_DATA_(BLT_I18NCONTEXT_ID_BRUSH, "Surface"));
1106 
1107   surface->effector_weights = BKE_effector_add_weights(NULL);
1108 
1109   dynamicPaintSurface_updateType(surface);
1110 
1111   BLI_addtail(&canvas->surfaces, surface);
1112 
1113   return surface;
1114 }
1115 
1116 /*
1117  * Initialize modifier data
1118  */
dynamicPaint_createType(struct DynamicPaintModifierData * pmd,int type,struct Scene * scene)1119 bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene)
1120 {
1121   if (pmd) {
1122     if (type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
1123       DynamicPaintCanvasSettings *canvas;
1124       if (pmd->canvas) {
1125         dynamicPaint_freeCanvas(pmd);
1126       }
1127 
1128       canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings),
1129                                          "DynamicPaint Canvas");
1130       if (!canvas) {
1131         return false;
1132       }
1133       canvas->pmd = pmd;
1134 
1135       /* Create one surface */
1136       if (!dynamicPaint_createNewSurface(canvas, scene)) {
1137         return false;
1138       }
1139     }
1140     else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
1141       DynamicPaintBrushSettings *brush;
1142       if (pmd->brush) {
1143         dynamicPaint_freeBrush(pmd);
1144       }
1145 
1146       brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint");
1147       if (!brush) {
1148         return false;
1149       }
1150       brush->pmd = pmd;
1151 
1152       brush->psys = NULL;
1153 
1154       brush->flags = MOD_DPAINT_ABS_ALPHA | MOD_DPAINT_RAMP_ALPHA;
1155       brush->collision = MOD_DPAINT_COL_VOLUME;
1156 
1157       brush->r = 0.15f;
1158       brush->g = 0.4f;
1159       brush->b = 0.8f;
1160       brush->alpha = 1.0f;
1161       brush->wetness = 1.0f;
1162 
1163       brush->paint_distance = 1.0f;
1164       brush->proximity_falloff = MOD_DPAINT_PRFALL_SMOOTH;
1165 
1166       brush->particle_radius = 0.2f;
1167       brush->particle_smooth = 0.05f;
1168 
1169       brush->wave_type = MOD_DPAINT_WAVEB_CHANGE;
1170       brush->wave_factor = 1.0f;
1171       brush->wave_clamp = 0.0f;
1172       brush->smudge_strength = 0.3f;
1173       brush->max_velocity = 1.0f;
1174 
1175       /* Paint proximity falloff colorramp. */
1176       {
1177         CBData *ramp;
1178 
1179         brush->paint_ramp = BKE_colorband_add(false);
1180         if (!brush->paint_ramp) {
1181           return false;
1182         }
1183         ramp = brush->paint_ramp->data;
1184         /* Add default smooth-falloff ramp. */
1185         ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f;
1186         ramp[0].pos = 0.0f;
1187         ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].pos = 1.0f;
1188         ramp[1].a = 0.0f;
1189         pmd->brush->paint_ramp->tot = 2;
1190       }
1191 
1192       /* Brush velocity ramp. */
1193       {
1194         CBData *ramp;
1195 
1196         brush->vel_ramp = BKE_colorband_add(false);
1197         if (!brush->vel_ramp) {
1198           return false;
1199         }
1200         ramp = brush->vel_ramp->data;
1201         ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f;
1202         ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f;
1203         brush->paint_ramp->tot = 2;
1204       }
1205     }
1206   }
1207   else {
1208     return false;
1209   }
1210 
1211   return true;
1212 }
1213 
dynamicPaint_Modifier_copy(const struct DynamicPaintModifierData * pmd,struct DynamicPaintModifierData * tpmd,int flag)1214 void dynamicPaint_Modifier_copy(const struct DynamicPaintModifierData *pmd,
1215                                 struct DynamicPaintModifierData *tpmd,
1216                                 int flag)
1217 {
1218   /* Init modifier */
1219   tpmd->type = pmd->type;
1220   if (pmd->canvas) {
1221     dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_CANVAS, NULL);
1222   }
1223   if (pmd->brush) {
1224     dynamicPaint_createType(tpmd, MOD_DYNAMICPAINT_TYPE_BRUSH, NULL);
1225   }
1226 
1227   /* Copy data */
1228   if (tpmd->canvas) {
1229     DynamicPaintSurface *surface;
1230     tpmd->canvas->pmd = tpmd;
1231     /* free default surface */
1232     if (tpmd->canvas->surfaces.first) {
1233       dynamicPaint_freeSurface(tpmd, tpmd->canvas->surfaces.first);
1234     }
1235 
1236     tpmd->canvas->active_sur = pmd->canvas->active_sur;
1237 
1238     /* copy existing surfaces */
1239     for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
1240       DynamicPaintSurface *t_surface = dynamicPaint_createNewSurface(tpmd->canvas, NULL);
1241       if (flag & LIB_ID_CREATE_NO_MAIN) {
1242         /* TODO(sergey): Consider passing some tips to the surface
1243          * creation to avoid this allocate-and-free cache behavior. */
1244         BKE_ptcache_free_list(&t_surface->ptcaches);
1245         tpmd->modifier.flag |= eModifierFlag_SharedCaches;
1246         t_surface->ptcaches = surface->ptcaches;
1247         t_surface->pointcache = surface->pointcache;
1248       }
1249 
1250       /* surface settings */
1251       t_surface->brush_group = surface->brush_group;
1252       MEM_freeN(t_surface->effector_weights);
1253       t_surface->effector_weights = MEM_dupallocN(surface->effector_weights);
1254 
1255       BLI_strncpy(t_surface->name, surface->name, sizeof(t_surface->name));
1256       t_surface->format = surface->format;
1257       t_surface->type = surface->type;
1258       t_surface->disp_type = surface->disp_type;
1259       t_surface->image_fileformat = surface->image_fileformat;
1260       t_surface->effect_ui = surface->effect_ui;
1261       t_surface->init_color_type = surface->init_color_type;
1262       t_surface->flags = surface->flags;
1263       t_surface->effect = surface->effect;
1264 
1265       t_surface->image_resolution = surface->image_resolution;
1266       t_surface->substeps = surface->substeps;
1267       t_surface->start_frame = surface->start_frame;
1268       t_surface->end_frame = surface->end_frame;
1269 
1270       copy_v4_v4(t_surface->init_color, surface->init_color);
1271       t_surface->init_texture = surface->init_texture;
1272       BLI_strncpy(
1273           t_surface->init_layername, surface->init_layername, sizeof(t_surface->init_layername));
1274 
1275       t_surface->dry_speed = surface->dry_speed;
1276       t_surface->diss_speed = surface->diss_speed;
1277       t_surface->color_dry_threshold = surface->color_dry_threshold;
1278       t_surface->depth_clamp = surface->depth_clamp;
1279       t_surface->disp_factor = surface->disp_factor;
1280 
1281       t_surface->spread_speed = surface->spread_speed;
1282       t_surface->color_spread_speed = surface->color_spread_speed;
1283       t_surface->shrink_speed = surface->shrink_speed;
1284       t_surface->drip_vel = surface->drip_vel;
1285       t_surface->drip_acc = surface->drip_acc;
1286 
1287       t_surface->influence_scale = surface->influence_scale;
1288       t_surface->radius_scale = surface->radius_scale;
1289 
1290       t_surface->wave_damping = surface->wave_damping;
1291       t_surface->wave_speed = surface->wave_speed;
1292       t_surface->wave_timescale = surface->wave_timescale;
1293       t_surface->wave_spring = surface->wave_spring;
1294       t_surface->wave_smoothness = surface->wave_smoothness;
1295 
1296       BLI_strncpy(t_surface->uvlayer_name, surface->uvlayer_name, sizeof(t_surface->uvlayer_name));
1297       BLI_strncpy(t_surface->image_output_path,
1298                   surface->image_output_path,
1299                   sizeof(t_surface->image_output_path));
1300       BLI_strncpy(t_surface->output_name, surface->output_name, sizeof(t_surface->output_name));
1301       BLI_strncpy(t_surface->output_name2, surface->output_name2, sizeof(t_surface->output_name2));
1302     }
1303   }
1304   if (tpmd->brush) {
1305     DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush;
1306     t_brush->pmd = tpmd;
1307 
1308     t_brush->flags = brush->flags;
1309     t_brush->collision = brush->collision;
1310 
1311     t_brush->r = brush->r;
1312     t_brush->g = brush->g;
1313     t_brush->b = brush->b;
1314     t_brush->alpha = brush->alpha;
1315     t_brush->wetness = brush->wetness;
1316 
1317     t_brush->particle_radius = brush->particle_radius;
1318     t_brush->particle_smooth = brush->particle_smooth;
1319     t_brush->paint_distance = brush->paint_distance;
1320     t_brush->psys = brush->psys;
1321 
1322     if (brush->paint_ramp) {
1323       memcpy(t_brush->paint_ramp, brush->paint_ramp, sizeof(ColorBand));
1324     }
1325     if (brush->vel_ramp) {
1326       memcpy(t_brush->vel_ramp, brush->vel_ramp, sizeof(ColorBand));
1327     }
1328 
1329     t_brush->proximity_falloff = brush->proximity_falloff;
1330     t_brush->wave_type = brush->wave_type;
1331     t_brush->ray_dir = brush->ray_dir;
1332 
1333     t_brush->wave_factor = brush->wave_factor;
1334     t_brush->wave_clamp = brush->wave_clamp;
1335     t_brush->max_velocity = brush->max_velocity;
1336     t_brush->smudge_strength = brush->smudge_strength;
1337   }
1338 }
1339 
1340 /* allocates surface data depending on surface type */
dynamicPaint_allocateSurfaceType(DynamicPaintSurface * surface)1341 static void dynamicPaint_allocateSurfaceType(DynamicPaintSurface *surface)
1342 {
1343   PaintSurfaceData *sData = surface->data;
1344 
1345   switch (surface->type) {
1346     case MOD_DPAINT_SURFACE_T_PAINT:
1347       sData->type_data = MEM_callocN(sizeof(PaintPoint) * sData->total_points,
1348                                      "DynamicPaintSurface Data");
1349       break;
1350     case MOD_DPAINT_SURFACE_T_DISPLACE:
1351       sData->type_data = MEM_callocN(sizeof(float) * sData->total_points,
1352                                      "DynamicPaintSurface DepthData");
1353       break;
1354     case MOD_DPAINT_SURFACE_T_WEIGHT:
1355       sData->type_data = MEM_callocN(sizeof(float) * sData->total_points,
1356                                      "DynamicPaintSurface WeightData");
1357       break;
1358     case MOD_DPAINT_SURFACE_T_WAVE:
1359       sData->type_data = MEM_callocN(sizeof(PaintWavePoint) * sData->total_points,
1360                                      "DynamicPaintSurface WaveData");
1361       break;
1362   }
1363 
1364   if (sData->type_data == NULL) {
1365     setError(surface->canvas, N_("Not enough free memory"));
1366   }
1367 }
1368 
surface_usesAdjDistance(DynamicPaintSurface * surface)1369 static bool surface_usesAdjDistance(DynamicPaintSurface *surface)
1370 {
1371   return ((surface->type == MOD_DPAINT_SURFACE_T_PAINT && surface->effect) ||
1372           (surface->type == MOD_DPAINT_SURFACE_T_WAVE));
1373 }
1374 
surface_usesAdjData(DynamicPaintSurface * surface)1375 static bool surface_usesAdjData(DynamicPaintSurface *surface)
1376 {
1377   return (surface_usesAdjDistance(surface) || (surface->format == MOD_DPAINT_SURFACE_F_VERTEX &&
1378                                                surface->flags & MOD_DPAINT_ANTIALIAS));
1379 }
1380 
1381 /* initialize surface adjacency data */
dynamicPaint_initAdjacencyData(DynamicPaintSurface * surface,const bool force_init)1382 static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const bool force_init)
1383 {
1384   PaintSurfaceData *sData = surface->data;
1385   Mesh *mesh = dynamicPaint_canvas_mesh_get(surface->canvas);
1386   PaintAdjData *ad;
1387   int *temp_data;
1388   int neigh_points = 0;
1389 
1390   if (!force_init && !surface_usesAdjData(surface)) {
1391     return;
1392   }
1393 
1394   if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1395     /* For vertex format, neighbors are connected by edges */
1396     neigh_points = 2 * mesh->totedge;
1397   }
1398   else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1399     neigh_points = sData->total_points * 8;
1400   }
1401 
1402   if (!neigh_points) {
1403     return;
1404   }
1405 
1406   /* allocate memory */
1407   ad = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data");
1408   if (!ad) {
1409     return;
1410   }
1411   ad->n_index = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Index");
1412   ad->n_num = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Counts");
1413   temp_data = MEM_callocN(sizeof(int) * sData->total_points, "Temp Adj Data");
1414   ad->n_target = MEM_callocN(sizeof(int) * neigh_points, "Surface Adj Targets");
1415   ad->flags = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Flags");
1416   ad->total_targets = neigh_points;
1417   ad->border = NULL;
1418   ad->total_border = 0;
1419 
1420   /* in case of allocation error, free memory */
1421   if (!ad->n_index || !ad->n_num || !ad->n_target || !temp_data) {
1422     dynamicPaint_freeAdjData(sData);
1423     if (temp_data) {
1424       MEM_freeN(temp_data);
1425     }
1426     setError(surface->canvas, N_("Not enough free memory"));
1427     return;
1428   }
1429 
1430   if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1431     /* For vertex format, count every vertex that is connected by an edge */
1432     int numOfEdges = mesh->totedge;
1433     int numOfPolys = mesh->totpoly;
1434     struct MEdge *edge = mesh->medge;
1435     struct MPoly *mpoly = mesh->mpoly;
1436     struct MLoop *mloop = mesh->mloop;
1437 
1438     /* count number of edges per vertex */
1439     for (int i = 0; i < numOfEdges; i++) {
1440       ad->n_num[edge[i].v1]++;
1441       ad->n_num[edge[i].v2]++;
1442 
1443       temp_data[edge[i].v1]++;
1444       temp_data[edge[i].v2]++;
1445     }
1446 
1447     /* also add number of vertices to temp_data
1448      * to locate points on "mesh edge" */
1449     for (int i = 0; i < numOfPolys; i++) {
1450       for (int j = 0; j < mpoly[i].totloop; j++) {
1451         temp_data[mloop[mpoly[i].loopstart + j].v]++;
1452       }
1453     }
1454 
1455     /* now check if total number of edges+faces for
1456      * each vertex is even, if not -> vertex is on mesh edge */
1457     for (int i = 0; i < sData->total_points; i++) {
1458       if ((temp_data[i] % 2) || (temp_data[i] < 4)) {
1459         ad->flags[i] |= ADJ_ON_MESH_EDGE;
1460       }
1461 
1462       /* reset temp data */
1463       temp_data[i] = 0;
1464     }
1465 
1466     /* order n_index array */
1467     int n_pos = 0;
1468     for (int i = 0; i < sData->total_points; i++) {
1469       ad->n_index[i] = n_pos;
1470       n_pos += ad->n_num[i];
1471     }
1472 
1473     /* and now add neighbor data using that info */
1474     for (int i = 0; i < numOfEdges; i++) {
1475       /* first vertex */
1476       int index = edge[i].v1;
1477       n_pos = ad->n_index[index] + temp_data[index];
1478       ad->n_target[n_pos] = edge[i].v2;
1479       temp_data[index]++;
1480 
1481       /* second vertex */
1482       index = edge[i].v2;
1483       n_pos = ad->n_index[index] + temp_data[index];
1484       ad->n_target[n_pos] = edge[i].v1;
1485       temp_data[index]++;
1486     }
1487   }
1488   else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1489     /* for image sequences, only allocate memory.
1490      * bake initialization takes care of rest */
1491   }
1492 
1493   MEM_freeN(temp_data);
1494 }
1495 
1496 typedef struct DynamicPaintSetInitColorData {
1497   const DynamicPaintSurface *surface;
1498 
1499   const MLoop *mloop;
1500   const MLoopUV *mloopuv;
1501   const MLoopTri *mlooptri;
1502   const MLoopCol *mloopcol;
1503   struct ImagePool *pool;
1504 
1505   const bool scene_color_manage;
1506 } DynamicPaintSetInitColorData;
1507 
dynamic_paint_set_init_color_tex_to_vcol_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1508 static void dynamic_paint_set_init_color_tex_to_vcol_cb(
1509     void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
1510 {
1511   const DynamicPaintSetInitColorData *data = userdata;
1512 
1513   const PaintSurfaceData *sData = data->surface->data;
1514   PaintPoint *pPoint = (PaintPoint *)sData->type_data;
1515 
1516   const MLoop *mloop = data->mloop;
1517   const MLoopTri *mlooptri = data->mlooptri;
1518   const MLoopUV *mloopuv = data->mloopuv;
1519   struct ImagePool *pool = data->pool;
1520   Tex *tex = data->surface->init_texture;
1521 
1522   const bool scene_color_manage = data->scene_color_manage;
1523 
1524   float uv[3] = {0.0f};
1525 
1526   for (int j = 3; j--;) {
1527     TexResult texres = {0};
1528     const unsigned int vert = mloop[mlooptri[i].tri[j]].v;
1529 
1530     /* remap to [-1.0, 1.0] */
1531     uv[0] = mloopuv[mlooptri[i].tri[j]].uv[0] * 2.0f - 1.0f;
1532     uv[1] = mloopuv[mlooptri[i].tri[j]].uv[1] * 2.0f - 1.0f;
1533 
1534     multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false);
1535 
1536     if (texres.tin > pPoint[vert].color[3]) {
1537       copy_v3_v3(pPoint[vert].color, &texres.tr);
1538       pPoint[vert].color[3] = texres.tin;
1539     }
1540   }
1541 }
1542 
dynamic_paint_set_init_color_tex_to_imseq_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1543 static void dynamic_paint_set_init_color_tex_to_imseq_cb(
1544     void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
1545 {
1546   const DynamicPaintSetInitColorData *data = userdata;
1547 
1548   const PaintSurfaceData *sData = data->surface->data;
1549   PaintPoint *pPoint = (PaintPoint *)sData->type_data;
1550 
1551   const MLoopTri *mlooptri = data->mlooptri;
1552   const MLoopUV *mloopuv = data->mloopuv;
1553   Tex *tex = data->surface->init_texture;
1554   ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
1555   const int samples = (data->surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
1556 
1557   const bool scene_color_manage = data->scene_color_manage;
1558 
1559   float uv[9] = {0.0f};
1560   float uv_final[3] = {0.0f};
1561 
1562   TexResult texres = {0};
1563 
1564   /* collect all uvs */
1565   for (int j = 3; j--;) {
1566     copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]].uv);
1567   }
1568 
1569   /* interpolate final uv pos */
1570   interp_v3_v3v3v3(uv_final, &uv[0], &uv[3], &uv[6], f_data->barycentricWeights[i * samples].v);
1571   /* remap to [-1.0, 1.0] */
1572   uv_final[0] = uv_final[0] * 2.0f - 1.0f;
1573   uv_final[1] = uv_final[1] * 2.0f - 1.0f;
1574 
1575   multitex_ext_safe(tex, uv_final, &texres, NULL, scene_color_manage, false);
1576 
1577   /* apply color */
1578   copy_v3_v3(pPoint[i].color, &texres.tr);
1579   pPoint[i].color[3] = texres.tin;
1580 }
1581 
dynamic_paint_set_init_color_vcol_to_imseq_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1582 static void dynamic_paint_set_init_color_vcol_to_imseq_cb(
1583     void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
1584 {
1585   const DynamicPaintSetInitColorData *data = userdata;
1586 
1587   const PaintSurfaceData *sData = data->surface->data;
1588   PaintPoint *pPoint = (PaintPoint *)sData->type_data;
1589 
1590   const MLoopTri *mlooptri = data->mlooptri;
1591   const MLoopCol *mloopcol = data->mloopcol;
1592   ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
1593   const int samples = (data->surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
1594 
1595   const int tri_idx = f_data->uv_p[i].tri_index;
1596   float colors[3][4];
1597   float final_color[4];
1598 
1599   /* collect color values */
1600   for (int j = 3; j--;) {
1601     rgba_uchar_to_float(colors[j], (const unsigned char *)&mloopcol[mlooptri[tri_idx].tri[j]].r);
1602   }
1603 
1604   /* interpolate final color */
1605   interp_v4_v4v4v4(final_color, UNPACK3(colors), f_data->barycentricWeights[i * samples].v);
1606 
1607   copy_v4_v4(pPoint[i].color, final_color);
1608 }
1609 
dynamicPaint_setInitialColor(const Scene * scene,DynamicPaintSurface * surface)1610 static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface *surface)
1611 {
1612   PaintSurfaceData *sData = surface->data;
1613   PaintPoint *pPoint = (PaintPoint *)sData->type_data;
1614   Mesh *mesh = dynamicPaint_canvas_mesh_get(surface->canvas);
1615   const bool scene_color_manage = BKE_scene_check_color_management_enabled(scene);
1616 
1617   if (surface->type != MOD_DPAINT_SURFACE_T_PAINT) {
1618     return;
1619   }
1620 
1621   if (surface->init_color_type == MOD_DPAINT_INITIAL_NONE) {
1622     return;
1623   }
1624 
1625   /* Single color */
1626   if (surface->init_color_type == MOD_DPAINT_INITIAL_COLOR) {
1627     /* apply color to every surface point */
1628     for (int i = 0; i < sData->total_points; i++) {
1629       copy_v4_v4(pPoint[i].color, surface->init_color);
1630     }
1631   }
1632   /* UV mapped texture */
1633   else if (surface->init_color_type == MOD_DPAINT_INITIAL_TEXTURE) {
1634     Tex *tex = surface->init_texture;
1635 
1636     const MLoop *mloop = mesh->mloop;
1637     const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
1638     const int tottri = BKE_mesh_runtime_looptri_len(mesh);
1639     const MLoopUV *mloopuv = NULL;
1640 
1641     char uvname[MAX_CUSTOMDATA_LAYER_NAME];
1642 
1643     if (!tex) {
1644       return;
1645     }
1646 
1647     /* get uv map */
1648     CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, surface->init_layername, uvname);
1649     mloopuv = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvname);
1650     if (!mloopuv) {
1651       return;
1652     }
1653 
1654     /* for vertex surface loop through tfaces and find uv color
1655      * that provides highest alpha */
1656     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1657       struct ImagePool *pool = BKE_image_pool_new();
1658 
1659       DynamicPaintSetInitColorData data = {
1660           .surface = surface,
1661           .mloop = mloop,
1662           .mlooptri = mlooptri,
1663           .mloopuv = mloopuv,
1664           .pool = pool,
1665           .scene_color_manage = scene_color_manage,
1666       };
1667       TaskParallelSettings settings;
1668       BLI_parallel_range_settings_defaults(&settings);
1669       settings.use_threading = (tottri > 1000);
1670       BLI_task_parallel_range(
1671           0, tottri, &data, dynamic_paint_set_init_color_tex_to_vcol_cb, &settings);
1672       BKE_image_pool_free(pool);
1673     }
1674     else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1675       DynamicPaintSetInitColorData data = {
1676           .surface = surface,
1677           .mlooptri = mlooptri,
1678           .mloopuv = mloopuv,
1679           .scene_color_manage = scene_color_manage,
1680       };
1681       TaskParallelSettings settings;
1682       BLI_parallel_range_settings_defaults(&settings);
1683       settings.use_threading = (sData->total_points > 1000);
1684       BLI_task_parallel_range(
1685           0, sData->total_points, &data, dynamic_paint_set_init_color_tex_to_imseq_cb, &settings);
1686     }
1687   }
1688   /* vertex color layer */
1689   else if (surface->init_color_type == MOD_DPAINT_INITIAL_VERTEXCOLOR) {
1690 
1691     /* for vertex surface, just copy colors from mcol */
1692     if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1693       const MLoop *mloop = mesh->mloop;
1694       const int totloop = mesh->totloop;
1695       const MLoopCol *col = CustomData_get_layer_named(
1696           &mesh->ldata, CD_MLOOPCOL, surface->init_layername);
1697       if (!col) {
1698         return;
1699       }
1700 
1701       for (int i = 0; i < totloop; i++) {
1702         rgba_uchar_to_float(pPoint[mloop[i].v].color, (const unsigned char *)&col[mloop[i].v].r);
1703       }
1704     }
1705     else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1706       const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
1707       MLoopCol *col = CustomData_get_layer_named(
1708           &mesh->ldata, CD_MLOOPCOL, surface->init_layername);
1709       if (!col) {
1710         return;
1711       }
1712 
1713       DynamicPaintSetInitColorData data = {
1714           .surface = surface,
1715           .mlooptri = mlooptri,
1716           .mloopcol = col,
1717       };
1718       TaskParallelSettings settings;
1719       BLI_parallel_range_settings_defaults(&settings);
1720       settings.use_threading = (sData->total_points > 1000);
1721       BLI_task_parallel_range(
1722           0, sData->total_points, &data, dynamic_paint_set_init_color_vcol_to_imseq_cb, &settings);
1723     }
1724   }
1725 }
1726 
1727 /* clears surface data back to zero */
dynamicPaint_clearSurface(const Scene * scene,DynamicPaintSurface * surface)1728 void dynamicPaint_clearSurface(const Scene *scene, DynamicPaintSurface *surface)
1729 {
1730   PaintSurfaceData *sData = surface->data;
1731   if (sData && sData->type_data) {
1732     unsigned int data_size;
1733 
1734     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1735       data_size = sizeof(PaintPoint);
1736     }
1737     else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
1738       data_size = sizeof(PaintWavePoint);
1739     }
1740     else {
1741       data_size = sizeof(float);
1742     }
1743 
1744     memset(sData->type_data, 0, data_size * sData->total_points);
1745 
1746     /* set initial color */
1747     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1748       dynamicPaint_setInitialColor(scene, surface);
1749     }
1750 
1751     if (sData->bData) {
1752       sData->bData->clear = 1;
1753     }
1754   }
1755 }
1756 
1757 /* completely (re)initializes surface (only for point cache types)*/
dynamicPaint_resetSurface(const Scene * scene,DynamicPaintSurface * surface)1758 bool dynamicPaint_resetSurface(const Scene *scene, DynamicPaintSurface *surface)
1759 {
1760   int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
1761   /* free existing data */
1762   if (surface->data) {
1763     dynamicPaint_freeSurfaceData(surface);
1764   }
1765 
1766   /* don't reallocate for image sequence types. they get handled only on bake */
1767   if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
1768     return true;
1769   }
1770   if (numOfPoints < 1) {
1771     return false;
1772   }
1773 
1774   /* allocate memory */
1775   surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
1776   if (!surface->data) {
1777     return false;
1778   }
1779 
1780   /* allocate data depending on surface type and format */
1781   surface->data->total_points = numOfPoints;
1782   dynamicPaint_allocateSurfaceType(surface);
1783   dynamicPaint_initAdjacencyData(surface, false);
1784 
1785   /* set initial color */
1786   if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1787     dynamicPaint_setInitialColor(scene, surface);
1788   }
1789 
1790   return true;
1791 }
1792 
1793 /* make sure allocated surface size matches current requirements */
dynamicPaint_checkSurfaceData(const Scene * scene,DynamicPaintSurface * surface)1794 static bool dynamicPaint_checkSurfaceData(const Scene *scene, DynamicPaintSurface *surface)
1795 {
1796   if (!surface->data ||
1797       ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) {
1798     return dynamicPaint_resetSurface(scene, surface);
1799   }
1800   return true;
1801 }
1802 
1803 /***************************** Modifier processing ******************************/
1804 
1805 typedef struct DynamicPaintModifierApplyData {
1806   const DynamicPaintSurface *surface;
1807   Object *ob;
1808 
1809   MVert *mvert;
1810   const MLoop *mloop;
1811   const MPoly *mpoly;
1812 
1813   float (*fcolor)[4];
1814   MLoopCol *mloopcol;
1815   MLoopCol *mloopcol_wet;
1816 } DynamicPaintModifierApplyData;
1817 
dynamic_paint_apply_surface_displace_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1818 static void dynamic_paint_apply_surface_displace_cb(void *__restrict userdata,
1819                                                     const int i,
1820                                                     const TaskParallelTLS *__restrict UNUSED(tls))
1821 {
1822   const DynamicPaintModifierApplyData *data = userdata;
1823 
1824   const DynamicPaintSurface *surface = data->surface;
1825   MVert *mvert = data->mvert;
1826 
1827   float normal[3];
1828   const float *value = (float *)surface->data->type_data;
1829   const float val = value[i] * surface->disp_factor;
1830 
1831   normal_short_to_float_v3(normal, mvert[i].no);
1832 
1833   /* same as 'mvert[i].co[0] -= normal[0] * val' etc. */
1834   madd_v3_v3fl(mvert[i].co, normal, -val);
1835 }
1836 
1837 /* apply displacing vertex surface to the derived mesh */
dynamicPaint_applySurfaceDisplace(DynamicPaintSurface * surface,Mesh * result)1838 static void dynamicPaint_applySurfaceDisplace(DynamicPaintSurface *surface, Mesh *result)
1839 {
1840   PaintSurfaceData *sData = surface->data;
1841 
1842   if (!sData || surface->format != MOD_DPAINT_SURFACE_F_VERTEX) {
1843     return;
1844   }
1845 
1846   /* displace paint */
1847   if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
1848     MVert *mvert = result->mvert;
1849 
1850     DynamicPaintModifierApplyData data = {
1851         .surface = surface,
1852         .mvert = mvert,
1853     };
1854     TaskParallelSettings settings;
1855     BLI_parallel_range_settings_defaults(&settings);
1856     settings.use_threading = (sData->total_points > 10000);
1857     BLI_task_parallel_range(
1858         0, sData->total_points, &data, dynamic_paint_apply_surface_displace_cb, &settings);
1859   }
1860 }
1861 
dynamic_paint_apply_surface_vpaint_blend_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1862 static void dynamic_paint_apply_surface_vpaint_blend_cb(
1863     void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
1864 {
1865   const DynamicPaintModifierApplyData *data = userdata;
1866 
1867   PaintPoint *pPoint = (PaintPoint *)data->surface->data->type_data;
1868   float(*fcolor)[4] = data->fcolor;
1869 
1870   /* blend dry and wet layer */
1871   blendColors(
1872       pPoint[i].color, pPoint[i].color[3], pPoint[i].e_color, pPoint[i].e_color[3], fcolor[i]);
1873 }
1874 
dynamic_paint_apply_surface_vpaint_cb(void * __restrict userdata,const int p_index,const TaskParallelTLS * __restrict UNUSED (tls))1875 static void dynamic_paint_apply_surface_vpaint_cb(void *__restrict userdata,
1876                                                   const int p_index,
1877                                                   const TaskParallelTLS *__restrict UNUSED(tls))
1878 {
1879   const DynamicPaintModifierApplyData *data = userdata;
1880 
1881   const MLoop *mloop = data->mloop;
1882   const MPoly *mpoly = data->mpoly;
1883 
1884   const DynamicPaintSurface *surface = data->surface;
1885   PaintPoint *pPoint = (PaintPoint *)surface->data->type_data;
1886   float(*fcolor)[4] = data->fcolor;
1887 
1888   MLoopCol *mloopcol = data->mloopcol;
1889   MLoopCol *mloopcol_wet = data->mloopcol_wet;
1890 
1891   for (int j = 0; j < mpoly[p_index].totloop; j++) {
1892     const int l_index = mpoly[p_index].loopstart + j;
1893     const int v_index = mloop[l_index].v;
1894 
1895     /* save layer data to output layer */
1896     /* apply color */
1897     if (mloopcol) {
1898       rgba_float_to_uchar((unsigned char *)&mloopcol[l_index].r, fcolor[v_index]);
1899     }
1900     /* apply wetness */
1901     if (mloopcol_wet) {
1902       const char c = unit_float_to_uchar_clamp(pPoint[v_index].wetness);
1903       mloopcol_wet[l_index].r = c;
1904       mloopcol_wet[l_index].g = c;
1905       mloopcol_wet[l_index].b = c;
1906       mloopcol_wet[l_index].a = 255;
1907     }
1908   }
1909 }
1910 
dynamic_paint_apply_surface_wave_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1911 static void dynamic_paint_apply_surface_wave_cb(void *__restrict userdata,
1912                                                 const int i,
1913                                                 const TaskParallelTLS *__restrict UNUSED(tls))
1914 {
1915   const DynamicPaintModifierApplyData *data = userdata;
1916 
1917   PaintWavePoint *wPoint = (PaintWavePoint *)data->surface->data->type_data;
1918   MVert *mvert = data->mvert;
1919   float normal[3];
1920 
1921   normal_short_to_float_v3(normal, mvert[i].no);
1922   madd_v3_v3fl(mvert[i].co, normal, wPoint[i].height);
1923 }
1924 
1925 /*
1926  * Apply canvas data to the object derived mesh
1927  */
dynamicPaint_Modifier_apply(DynamicPaintModifierData * pmd,Object * ob,Mesh * mesh)1928 static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *ob, Mesh *mesh)
1929 {
1930   Mesh *result = BKE_mesh_copy_for_eval(mesh, false);
1931 
1932   if (pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING) &&
1933       pmd->type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
1934 
1935     DynamicPaintSurface *surface;
1936     bool update_normals = false;
1937 
1938     /* loop through surfaces */
1939     for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
1940       PaintSurfaceData *sData = surface->data;
1941 
1942       if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && sData) {
1943         if (!(surface->flags & MOD_DPAINT_ACTIVE)) {
1944           continue;
1945         }
1946 
1947         /* process vertex surface previews */
1948         if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
1949 
1950           /* vertex color paint */
1951           if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
1952             MLoop *mloop = result->mloop;
1953             const int totloop = result->totloop;
1954             MPoly *mpoly = result->mpoly;
1955             const int totpoly = result->totpoly;
1956 
1957             /* paint is stored on dry and wet layers, so mix final color first */
1958             float(*fcolor)[4] = MEM_callocN(sizeof(*fcolor) * sData->total_points,
1959                                             "Temp paint color");
1960 
1961             DynamicPaintModifierApplyData data = {
1962                 .surface = surface,
1963                 .fcolor = fcolor,
1964             };
1965             {
1966               TaskParallelSettings settings;
1967               BLI_parallel_range_settings_defaults(&settings);
1968               settings.use_threading = (sData->total_points > 1000);
1969               BLI_task_parallel_range(0,
1970                                       sData->total_points,
1971                                       &data,
1972                                       dynamic_paint_apply_surface_vpaint_blend_cb,
1973                                       &settings);
1974             }
1975 
1976             /* paint layer */
1977             MLoopCol *mloopcol = CustomData_get_layer_named(
1978                 &result->ldata, CD_MLOOPCOL, surface->output_name);
1979             /* if output layer is lost from a constructive modifier, re-add it */
1980             if (!mloopcol && dynamicPaint_outputLayerExists(surface, ob, 0)) {
1981               mloopcol = CustomData_add_layer_named(
1982                   &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name);
1983             }
1984 
1985             /* wet layer */
1986             MLoopCol *mloopcol_wet = CustomData_get_layer_named(
1987                 &result->ldata, CD_MLOOPCOL, surface->output_name2);
1988             /* if output layer is lost from a constructive modifier, re-add it */
1989             if (!mloopcol_wet && dynamicPaint_outputLayerExists(surface, ob, 1)) {
1990               mloopcol_wet = CustomData_add_layer_named(
1991                   &result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, totloop, surface->output_name2);
1992             }
1993 
1994             data.ob = ob;
1995             data.mloop = mloop;
1996             data.mpoly = mpoly;
1997             data.mloopcol = mloopcol;
1998             data.mloopcol_wet = mloopcol_wet;
1999 
2000             {
2001               TaskParallelSettings settings;
2002               BLI_parallel_range_settings_defaults(&settings);
2003               settings.use_threading = (totpoly > 1000);
2004               BLI_task_parallel_range(
2005                   0, totpoly, &data, dynamic_paint_apply_surface_vpaint_cb, &settings);
2006             }
2007 
2008             MEM_freeN(fcolor);
2009 
2010             /* Mark tessellated CD layers as dirty. */
2011             // result->dirty |= DM_DIRTY_TESS_CDLAYERS;
2012           }
2013           /* vertex group paint */
2014           else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
2015             int defgrp_index = BKE_object_defgroup_name_index(ob, surface->output_name);
2016             MDeformVert *dvert = CustomData_get_layer(&result->vdata, CD_MDEFORMVERT);
2017             float *weight = (float *)sData->type_data;
2018 
2019             /* apply weights into a vertex group, if doesn't exists add a new layer */
2020             if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) {
2021               dvert = CustomData_add_layer(
2022                   &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, sData->total_points);
2023               /* Make the dvert layer easily accessible from the mesh data. */
2024               result->dvert = dvert;
2025             }
2026             if (defgrp_index != -1 && dvert) {
2027               for (int i = 0; i < sData->total_points; i++) {
2028                 MDeformVert *dv = &dvert[i];
2029                 MDeformWeight *def_weight = BKE_defvert_find_index(dv, defgrp_index);
2030 
2031                 /* skip if weight value is 0 and no existing weight is found */
2032                 if ((def_weight != NULL) || (weight[i] != 0.0f)) {
2033                   /* if not found, add a weight for it */
2034                   if (def_weight == NULL) {
2035                     def_weight = BKE_defvert_ensure_index(dv, defgrp_index);
2036                   }
2037 
2038                   /* set weight value */
2039                   def_weight->weight = weight[i];
2040                 }
2041               }
2042             }
2043           }
2044           /* wave simulation */
2045           else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
2046             MVert *mvert = result->mvert;
2047 
2048             DynamicPaintModifierApplyData data = {
2049                 .surface = surface,
2050                 .mvert = mvert,
2051             };
2052             TaskParallelSettings settings;
2053             BLI_parallel_range_settings_defaults(&settings);
2054             settings.use_threading = (sData->total_points > 1000);
2055             BLI_task_parallel_range(
2056                 0, sData->total_points, &data, dynamic_paint_apply_surface_wave_cb, &settings);
2057             update_normals = true;
2058           }
2059 
2060           /* displace */
2061           if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
2062             dynamicPaint_applySurfaceDisplace(surface, result);
2063             update_normals = true;
2064           }
2065         }
2066       }
2067     }
2068 
2069     if (update_normals) {
2070       result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
2071     }
2072   }
2073   /* make a copy of mesh to use as brush data */
2074   else if (pmd->brush && pmd->type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
2075     DynamicPaintRuntime *runtime_data = dynamicPaint_Modifier_runtime_ensure(pmd);
2076     if (runtime_data->brush_mesh != NULL) {
2077       BKE_id_free(NULL, runtime_data->brush_mesh);
2078     }
2079     runtime_data->brush_mesh = BKE_mesh_copy_for_eval(result, false);
2080   }
2081 
2082   return result;
2083 }
2084 
2085 /* update cache frame range */
dynamicPaint_cacheUpdateFrames(DynamicPaintSurface * surface)2086 void dynamicPaint_cacheUpdateFrames(DynamicPaintSurface *surface)
2087 {
2088   if (surface->pointcache) {
2089     surface->pointcache->startframe = surface->start_frame;
2090     surface->pointcache->endframe = surface->end_frame;
2091   }
2092 }
2093 
canvas_copyMesh(DynamicPaintCanvasSettings * canvas,Mesh * mesh)2094 static void canvas_copyMesh(DynamicPaintCanvasSettings *canvas, Mesh *mesh)
2095 {
2096   DynamicPaintRuntime *runtime = dynamicPaint_Modifier_runtime_ensure(canvas->pmd);
2097   if (runtime->canvas_mesh != NULL) {
2098     BKE_id_free(NULL, runtime->canvas_mesh);
2099   }
2100 
2101   runtime->canvas_mesh = BKE_mesh_copy_for_eval(mesh, false);
2102 }
2103 
2104 /*
2105  * Updates derived mesh copy and processes dynamic paint step / caches.
2106  */
dynamicPaint_frameUpdate(DynamicPaintModifierData * pmd,struct Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * mesh)2107 static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd,
2108                                      struct Depsgraph *depsgraph,
2109                                      Scene *scene,
2110                                      Object *ob,
2111                                      Mesh *mesh)
2112 {
2113   if (pmd->canvas) {
2114     DynamicPaintCanvasSettings *canvas = pmd->canvas;
2115     DynamicPaintSurface *surface = canvas->surfaces.first;
2116 
2117     /* update derived mesh copy */
2118     canvas_copyMesh(canvas, mesh);
2119 
2120     /* in case image sequence baking, stop here */
2121     if (canvas->flags & MOD_DPAINT_BAKING) {
2122       return;
2123     }
2124 
2125     /* loop through surfaces */
2126     for (; surface; surface = surface->next) {
2127       int current_frame = (int)scene->r.cfra;
2128       bool no_surface_data;
2129 
2130       /* free bake data if not required anymore */
2131       surface_freeUnusedData(surface);
2132 
2133       /* image sequences are handled by bake operator */
2134       if ((surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) ||
2135           !(surface->flags & MOD_DPAINT_ACTIVE)) {
2136         continue;
2137       }
2138 
2139       /* make sure surface is valid */
2140       no_surface_data = surface->data == NULL;
2141       if (!dynamicPaint_checkSurfaceData(scene, surface)) {
2142         continue;
2143       }
2144 
2145       /* limit frame range */
2146       CLAMP(current_frame, surface->start_frame, surface->end_frame);
2147 
2148       if (no_surface_data || current_frame != surface->current_frame ||
2149           (int)scene->r.cfra == surface->start_frame) {
2150         PointCache *cache = surface->pointcache;
2151         PTCacheID pid;
2152         surface->current_frame = current_frame;
2153 
2154         /* read point cache */
2155         BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface);
2156         pid.cache->startframe = surface->start_frame;
2157         pid.cache->endframe = surface->end_frame;
2158         BKE_ptcache_id_time(&pid, scene, (float)scene->r.cfra, NULL, NULL, NULL);
2159 
2160         /* reset non-baked cache at first frame */
2161         if ((int)scene->r.cfra == surface->start_frame && !(cache->flag & PTCACHE_BAKED)) {
2162           cache->flag |= PTCACHE_REDO_NEEDED;
2163           BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
2164           cache->flag &= ~PTCACHE_REDO_NEEDED;
2165         }
2166 
2167         /* try to read from cache */
2168         bool can_simulate = ((int)scene->r.cfra == current_frame) &&
2169                             !(cache->flag & PTCACHE_BAKED);
2170 
2171         if (BKE_ptcache_read(&pid, (float)scene->r.cfra, can_simulate)) {
2172           BKE_ptcache_validate(cache, (int)scene->r.cfra);
2173         }
2174         /* if read failed and we're on surface range do recalculate */
2175         else if (can_simulate) {
2176           /* calculate surface frame */
2177           canvas->flags |= MOD_DPAINT_BAKING;
2178           dynamicPaint_calculateFrame(surface, depsgraph, scene, ob, current_frame);
2179           canvas->flags &= ~MOD_DPAINT_BAKING;
2180 
2181           /* restore canvas mesh if required */
2182           if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE &&
2183               surface->flags & MOD_DPAINT_DISP_INCREMENTAL && surface->next) {
2184             canvas_copyMesh(canvas, mesh);
2185           }
2186 
2187           BKE_ptcache_validate(cache, surface->current_frame);
2188           BKE_ptcache_write(&pid, surface->current_frame);
2189         }
2190       }
2191     }
2192   }
2193 }
2194 
2195 /* Modifier call. Processes dynamic paint modifier step. */
dynamicPaint_Modifier_do(DynamicPaintModifierData * pmd,struct Depsgraph * depsgraph,Scene * scene,Object * ob,Mesh * mesh)2196 Mesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd,
2197                                struct Depsgraph *depsgraph,
2198                                Scene *scene,
2199                                Object *ob,
2200                                Mesh *mesh)
2201 {
2202   /* Update canvas data for a new frame */
2203   dynamicPaint_frameUpdate(pmd, depsgraph, scene, ob, mesh);
2204 
2205   /* Return output mesh */
2206   return dynamicPaint_Modifier_apply(pmd, ob, mesh);
2207 }
2208 
2209 /* -------------------------------------------------------------------- */
2210 /** \name Image Sequence / UV Image Surface Calls
2211  * \{ */
2212 
2213 /* Create a surface for uv image sequence format. */
2214 #define JITTER_SAMPLES \
2215   { \
2216     0.0f, 0.0f, -0.2f, -0.4f, 0.2f, 0.4f, 0.4f, -0.2f, -0.4f, 0.3f, \
2217   }
2218 
2219 typedef struct DynamicPaintCreateUVSurfaceData {
2220   const DynamicPaintSurface *surface;
2221 
2222   PaintUVPoint *tempPoints;
2223   Vec3f *tempWeights;
2224 
2225   const MLoopTri *mlooptri;
2226   const MLoopUV *mloopuv;
2227   const MLoop *mloop;
2228   const int tottri;
2229 
2230   const Bounds2D *faceBB;
2231   uint32_t *active_points;
2232 } DynamicPaintCreateUVSurfaceData;
2233 
dynamic_paint_create_uv_surface_direct_cb(void * __restrict userdata,const int ty,const TaskParallelTLS * __restrict UNUSED (tls))2234 static void dynamic_paint_create_uv_surface_direct_cb(
2235     void *__restrict userdata, const int ty, const TaskParallelTLS *__restrict UNUSED(tls))
2236 {
2237   const DynamicPaintCreateUVSurfaceData *data = userdata;
2238 
2239   const DynamicPaintSurface *surface = data->surface;
2240   PaintUVPoint *tempPoints = data->tempPoints;
2241   Vec3f *tempWeights = data->tempWeights;
2242 
2243   const MLoopTri *mlooptri = data->mlooptri;
2244   const MLoopUV *mloopuv = data->mloopuv;
2245   const MLoop *mloop = data->mloop;
2246   const int tottri = data->tottri;
2247 
2248   const Bounds2D *faceBB = data->faceBB;
2249 
2250   const float jitter5sample[10] = JITTER_SAMPLES;
2251   const int aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
2252   const int w = surface->image_resolution;
2253   const int h = w;
2254 
2255   for (int tx = 0; tx < w; tx++) {
2256     const int index = tx + w * ty;
2257     PaintUVPoint *tPoint = &tempPoints[index];
2258     float point[5][2];
2259 
2260     /* Init per pixel settings */
2261     tPoint->tri_index = -1;
2262     tPoint->neighbor_pixel = -1;
2263     tPoint->pixel_index = index;
2264 
2265     /* Actual pixel center, used when collision is found */
2266     point[0][0] = ((float)tx + 0.5f) / w;
2267     point[0][1] = ((float)ty + 0.5f) / h;
2268 
2269     /*
2270      * A pixel middle sample isn't enough to find very narrow polygons
2271      * So using 4 samples of each corner too
2272      */
2273     point[1][0] = ((float)tx) / w;
2274     point[1][1] = ((float)ty) / h;
2275 
2276     point[2][0] = ((float)tx + 1) / w;
2277     point[2][1] = ((float)ty) / h;
2278 
2279     point[3][0] = ((float)tx) / w;
2280     point[3][1] = ((float)ty + 1) / h;
2281 
2282     point[4][0] = ((float)tx + 1) / w;
2283     point[4][1] = ((float)ty + 1) / h;
2284 
2285     /* Loop through samples, starting from middle point */
2286     for (int sample = 0; sample < 5; sample++) {
2287       /* Loop through every face in the mesh */
2288       /* XXX TODO This is *horrible* with big meshes, should use a 2D BVHTree over UV tris here! */
2289       for (int i = 0; i < tottri; i++) {
2290         /* Check uv bb */
2291         if ((faceBB[i].min[0] > point[sample][0]) || (faceBB[i].min[1] > point[sample][1]) ||
2292             (faceBB[i].max[0] < point[sample][0]) || (faceBB[i].max[1] < point[sample][1])) {
2293           continue;
2294         }
2295 
2296         const float *uv1 = mloopuv[mlooptri[i].tri[0]].uv;
2297         const float *uv2 = mloopuv[mlooptri[i].tri[1]].uv;
2298         const float *uv3 = mloopuv[mlooptri[i].tri[2]].uv;
2299 
2300         /* If point is inside the face */
2301         if (isect_point_tri_v2(point[sample], uv1, uv2, uv3) != 0) {
2302           float uv[2];
2303 
2304           /* Add b-weights per anti-aliasing sample */
2305           for (int j = 0; j < aa_samples; j++) {
2306             uv[0] = point[0][0] + jitter5sample[j * 2] / w;
2307             uv[1] = point[0][1] + jitter5sample[j * 2 + 1] / h;
2308 
2309             barycentric_weights_v2(uv1, uv2, uv3, uv, tempWeights[index * aa_samples + j].v);
2310           }
2311 
2312           /* Set surface point face values */
2313           tPoint->tri_index = i;
2314 
2315           /* save vertex indexes */
2316           tPoint->v1 = mloop[mlooptri[i].tri[0]].v;
2317           tPoint->v2 = mloop[mlooptri[i].tri[1]].v;
2318           tPoint->v3 = mloop[mlooptri[i].tri[2]].v;
2319 
2320           sample = 5; /* make sure we exit sample loop as well */
2321           break;
2322         }
2323       }
2324     }
2325   }
2326 }
2327 
dynamic_paint_create_uv_surface_neighbor_cb(void * __restrict userdata,const int ty,const TaskParallelTLS * __restrict UNUSED (tls))2328 static void dynamic_paint_create_uv_surface_neighbor_cb(
2329     void *__restrict userdata, const int ty, const TaskParallelTLS *__restrict UNUSED(tls))
2330 {
2331   const DynamicPaintCreateUVSurfaceData *data = userdata;
2332 
2333   const DynamicPaintSurface *surface = data->surface;
2334   PaintUVPoint *tempPoints = data->tempPoints;
2335   Vec3f *tempWeights = data->tempWeights;
2336 
2337   const MLoopTri *mlooptri = data->mlooptri;
2338   const MLoopUV *mloopuv = data->mloopuv;
2339   const MLoop *mloop = data->mloop;
2340 
2341   uint32_t *active_points = data->active_points;
2342 
2343   const float jitter5sample[10] = JITTER_SAMPLES;
2344   const int aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
2345   const int w = surface->image_resolution;
2346   const int h = w;
2347 
2348   for (int tx = 0; tx < w; tx++) {
2349     const int index = tx + w * ty;
2350     PaintUVPoint *tPoint = &tempPoints[index];
2351 
2352     /* If point isn't on canvas mesh */
2353     if (tPoint->tri_index == -1) {
2354       float point[2];
2355 
2356       /* get loop area */
2357       const int u_min = (tx > 0) ? -1 : 0;
2358       const int u_max = (tx < (w - 1)) ? 1 : 0;
2359       const int v_min = (ty > 0) ? -1 : 0;
2360       const int v_max = (ty < (h - 1)) ? 1 : 0;
2361 
2362       point[0] = ((float)tx + 0.5f) / w;
2363       point[1] = ((float)ty + 0.5f) / h;
2364 
2365       /* search through defined area for neighbor, checking grid directions first */
2366       for (int ni = 0; ni < 8; ni++) {
2367         int u = neighStraightX[ni];
2368         int v = neighStraightY[ni];
2369 
2370         if (u >= u_min && u <= u_max && v >= v_min && v <= v_max) {
2371           /* if not this pixel itself */
2372           if (u != 0 || v != 0) {
2373             const int ind = (tx + u) + w * (ty + v);
2374 
2375             /* if neighbor has index */
2376             if (tempPoints[ind].neighbor_pixel == -1 && tempPoints[ind].tri_index != -1) {
2377               float uv[2];
2378               const int i = tempPoints[ind].tri_index;
2379               const float *uv1 = mloopuv[mlooptri[i].tri[0]].uv;
2380               const float *uv2 = mloopuv[mlooptri[i].tri[1]].uv;
2381               const float *uv3 = mloopuv[mlooptri[i].tri[2]].uv;
2382 
2383               /* tri index */
2384               /* There is a low possibility of actually having a neighbor point which tri is
2385                * already set from another neighbor in a separate thread here.
2386                * Checking for both tri_index and neighbor_pixel above reduces that probability
2387                * but it remains possible.
2388                * That atomic op (and its memory fence) ensures tPoint->neighbor_pixel is set
2389                * to non--1 *before* its tri_index is set (i.e. that it cannot be used a neighbor).
2390                */
2391               tPoint->neighbor_pixel = ind - 1;
2392               atomic_add_and_fetch_uint32(&tPoint->neighbor_pixel, 1);
2393               tPoint->tri_index = i;
2394 
2395               /* Now calculate pixel data for this pixel as it was on polygon surface */
2396               /* Add b-weights per anti-aliasing sample */
2397               for (int j = 0; j < aa_samples; j++) {
2398                 uv[0] = point[0] + jitter5sample[j * 2] / w;
2399                 uv[1] = point[1] + jitter5sample[j * 2 + 1] / h;
2400                 barycentric_weights_v2(uv1, uv2, uv3, uv, tempWeights[index * aa_samples + j].v);
2401               }
2402 
2403               /* save vertex indexes */
2404               tPoint->v1 = mloop[mlooptri[i].tri[0]].v;
2405               tPoint->v2 = mloop[mlooptri[i].tri[1]].v;
2406               tPoint->v3 = mloop[mlooptri[i].tri[2]].v;
2407 
2408               break;
2409             }
2410           }
2411         }
2412       }
2413     }
2414 
2415     /* Increase the final number of active surface points if relevant. */
2416     if (tPoint->tri_index != -1) {
2417       atomic_add_and_fetch_uint32(active_points, 1);
2418     }
2419   }
2420 }
2421 
2422 #undef JITTER_SAMPLES
2423 
dist_squared_to_looptri_uv_edges(const MLoopTri * mlooptri,const MLoopUV * mloopuv,int tri_index,const float point[2])2424 static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
2425                                               const MLoopUV *mloopuv,
2426                                               int tri_index,
2427                                               const float point[2])
2428 {
2429   BLI_assert(tri_index >= 0);
2430 
2431   float min_distance = FLT_MAX;
2432 
2433   for (int i = 0; i < 3; i++) {
2434     const float dist_squared = dist_squared_to_line_segment_v2(
2435         point,
2436         mloopuv[mlooptri[tri_index].tri[(i + 0)]].uv,
2437         mloopuv[mlooptri[tri_index].tri[(i + 1) % 3]].uv);
2438 
2439     if (dist_squared < min_distance) {
2440       min_distance = dist_squared;
2441     }
2442   }
2443 
2444   return min_distance;
2445 }
2446 
2447 typedef struct DynamicPaintFindIslandBorderData {
2448   const MeshElemMap *vert_to_looptri_map;
2449   int w, h, px, py;
2450 
2451   int best_index;
2452   float best_weight;
2453 } DynamicPaintFindIslandBorderData;
2454 
2455 static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceData *data,
2456                                              DynamicPaintFindIslandBorderData *bdata,
2457                                              int tri_index,
2458                                              const float pixel[2],
2459                                              int in_edge,
2460                                              int depth);
2461 
2462 /* Tries to find the neighboring pixel in given (uv space) direction.
2463  * Result is used by effect system to move paint on the surface.
2464  *
2465  * px, py : origin pixel x and y
2466  * n_index : lookup direction index (use neighX, neighY to get final index)
2467  */
dynamic_paint_find_neighbor_pixel(const DynamicPaintCreateUVSurfaceData * data,const MeshElemMap * vert_to_looptri_map,const int w,const int h,const int px,const int py,const int n_index)2468 static int dynamic_paint_find_neighbor_pixel(const DynamicPaintCreateUVSurfaceData *data,
2469                                              const MeshElemMap *vert_to_looptri_map,
2470                                              const int w,
2471                                              const int h,
2472                                              const int px,
2473                                              const int py,
2474                                              const int n_index)
2475 {
2476   /* Note: Current method only uses polygon edges to detect neighboring pixels.
2477    *       -> It doesn't always lead to the optimum pixel but is accurate enough
2478    *          and faster/simpler than including possible face tip point links)
2479    */
2480 
2481   /* shift position by given n_index */
2482   const int x = px + neighX[n_index];
2483   const int y = py + neighY[n_index];
2484 
2485   if (x < 0 || x >= w || y < 0 || y >= h) {
2486     return OUT_OF_TEXTURE;
2487   }
2488 
2489   const PaintUVPoint *tempPoints = data->tempPoints;
2490   const PaintUVPoint *tPoint = &tempPoints[x + w * y];   /* UV neighbor */
2491   const PaintUVPoint *cPoint = &tempPoints[px + w * py]; /* Origin point */
2492 
2493   /* Check if shifted point is on same face -> it's a correct neighbor
2494    * (and if it isn't marked as an "edge pixel") */
2495   if ((tPoint->tri_index == cPoint->tri_index) && (tPoint->neighbor_pixel == -1)) {
2496     return (x + w * y);
2497   }
2498 
2499   /* Even if shifted point is on another face
2500    * -> use this point.
2501    *
2502    * !! Replace with "is uv faces linked" check !!
2503    * This should work fine as long as uv island margin is > 1 pixel.
2504    */
2505   if ((tPoint->tri_index != -1) && (tPoint->neighbor_pixel == -1)) {
2506     return (x + w * y);
2507   }
2508 
2509   /* If we get here, the actual neighboring pixel is located on a non-linked uv face,
2510    * and we have to find its "real" position.
2511    *
2512    * Simple neighboring face finding algorithm:
2513    *   - find closest uv edge to shifted pixel and get the another face that shares that edge
2514    *   - find corresponding position of that new face edge in uv space
2515    *
2516    * TODO: Implement something more accurate / optimized?
2517    */
2518   {
2519     DynamicPaintFindIslandBorderData bdata = {
2520         .vert_to_looptri_map = vert_to_looptri_map,
2521         .w = w,
2522         .h = h,
2523         .px = px,
2524         .py = py,
2525         .best_index = NOT_FOUND,
2526         .best_weight = 1.0f,
2527     };
2528 
2529     float pixel[2];
2530 
2531     pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w;
2532     pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h;
2533 
2534     /* Do a small recursive search for the best island edge. */
2535     dynamic_paint_find_island_border(data, &bdata, cPoint->tri_index, pixel, -1, 5);
2536 
2537     return bdata.best_index;
2538   }
2539 }
2540 
dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceData * data,DynamicPaintFindIslandBorderData * bdata,int tri_index,const float pixel[2],int in_edge,int depth)2541 static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceData *data,
2542                                              DynamicPaintFindIslandBorderData *bdata,
2543                                              int tri_index,
2544                                              const float pixel[2],
2545                                              int in_edge,
2546                                              int depth)
2547 {
2548   const MLoop *mloop = data->mloop;
2549   const MLoopTri *mlooptri = data->mlooptri;
2550   const MLoopUV *mloopuv = data->mloopuv;
2551 
2552   const unsigned int *loop_idx = mlooptri[tri_index].tri;
2553 
2554   /* Enumerate all edges of the triangle, rotating the vertex list accordingly. */
2555   for (int edge_idx = 0; edge_idx < 3; edge_idx++) {
2556     /* but not the edge we have just recursed through */
2557     if (edge_idx == in_edge) {
2558       continue;
2559     }
2560 
2561     float uv0[2], uv1[2], uv2[2];
2562 
2563     copy_v2_v2(uv0, mloopuv[loop_idx[(edge_idx + 0)]].uv);
2564     copy_v2_v2(uv1, mloopuv[loop_idx[(edge_idx + 1) % 3]].uv);
2565     copy_v2_v2(uv2, mloopuv[loop_idx[(edge_idx + 2) % 3]].uv);
2566 
2567     /* Verify the target point is on the opposite side of the edge from the third triangle
2568      * vertex, to ensure that we always move closer to the goal point. */
2569     const float sidep = line_point_side_v2(uv0, uv1, pixel);
2570     const float side2 = line_point_side_v2(uv0, uv1, uv2);
2571 
2572     if (side2 == 0.0f) {
2573       continue;
2574     }
2575 
2576     /* Hack: allow all edges of the original triangle */
2577     const bool correct_side = (in_edge == -1) || (sidep < 0 && side2 > 0) ||
2578                               (sidep > 0 && side2 < 0);
2579 
2580     /* Allow exactly on edge for the non-recursive case */
2581     if (!correct_side && sidep != 0.0f) {
2582       continue;
2583     }
2584 
2585     /* Now find another face that is linked to that edge. */
2586     const int vert0 = mloop[loop_idx[(edge_idx + 0)]].v;
2587     const int vert1 = mloop[loop_idx[(edge_idx + 1) % 3]].v;
2588 
2589     /* Use a pre-computed vert-to-looptri mapping,
2590      * speeds up things a lot compared to looping over all loopti. */
2591     const MeshElemMap *map = &bdata->vert_to_looptri_map[vert0];
2592 
2593     bool found_other = false;
2594     int target_tri = -1;
2595     int target_edge = -1;
2596 
2597     float ouv0[2], ouv1[2];
2598 
2599     for (int i = 0; i < map->count && !found_other; i++) {
2600       const int lt_index = map->indices[i];
2601 
2602       if (lt_index == tri_index) {
2603         continue;
2604       }
2605 
2606       const unsigned int *other_loop_idx = mlooptri[lt_index].tri;
2607 
2608       /* Check edges for match, looping in the same order as the outer loop. */
2609       for (int j = 0; j < 3; j++) {
2610         const int overt0 = mloop[other_loop_idx[(j + 0)]].v;
2611         const int overt1 = mloop[other_loop_idx[(j + 1) % 3]].v;
2612 
2613         /* Allow for swapped vertex order */
2614         if (overt0 == vert0 && overt1 == vert1) {
2615           found_other = true;
2616           copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 0)]].uv);
2617           copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 1) % 3]].uv);
2618         }
2619         else if (overt0 == vert1 && overt1 == vert0) {
2620           found_other = true;
2621           copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 0)]].uv);
2622           copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 1) % 3]].uv);
2623         }
2624 
2625         if (found_other) {
2626           target_tri = lt_index;
2627           target_edge = j;
2628           break;
2629         }
2630       }
2631     }
2632 
2633     if (!found_other) {
2634       if (bdata->best_index < 0) {
2635         bdata->best_index = ON_MESH_EDGE;
2636       }
2637 
2638       continue;
2639     }
2640 
2641     /* If this edge is connected in UV space too, recurse */
2642     if (equals_v2v2(uv0, ouv0) && equals_v2v2(uv1, ouv1)) {
2643       if (depth > 0 && correct_side) {
2644         dynamic_paint_find_island_border(data, bdata, target_tri, pixel, target_edge, depth - 1);
2645       }
2646 
2647       continue;
2648     }
2649 
2650     /* Otherwise try to map to the other side of the edge.
2651      * First check if there already is a better solution. */
2652     const float dist_squared = dist_squared_to_line_segment_v2(pixel, uv0, uv1);
2653 
2654     if (bdata->best_index >= 0 && dist_squared >= bdata->best_weight) {
2655       continue;
2656     }
2657 
2658     /*
2659      * Find a point that is relatively at same edge position
2660      * on this other face UV
2661      */
2662     float closest_point[2], dir_vec[2], tgt_pixel[2];
2663 
2664     float lambda = closest_to_line_v2(closest_point, pixel, uv0, uv1);
2665     CLAMP(lambda, 0.0f, 1.0f);
2666 
2667     sub_v2_v2v2(dir_vec, ouv1, ouv0);
2668     madd_v2_v2v2fl(tgt_pixel, ouv0, dir_vec, lambda);
2669 
2670     int w = bdata->w, h = bdata->h, px = bdata->px, py = bdata->py;
2671 
2672     const int final_pixel[2] = {(int)floorf(tgt_pixel[0] * w), (int)floorf(tgt_pixel[1] * h)};
2673 
2674     /* If current pixel uv is outside of texture */
2675     if (final_pixel[0] < 0 || final_pixel[0] >= w || final_pixel[1] < 0 || final_pixel[1] >= h) {
2676       if (bdata->best_index == NOT_FOUND) {
2677         bdata->best_index = OUT_OF_TEXTURE;
2678       }
2679 
2680       continue;
2681     }
2682 
2683     const PaintUVPoint *tempPoints = data->tempPoints;
2684     int final_index = final_pixel[0] + w * final_pixel[1];
2685 
2686     /* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */
2687     if (final_index == (px + w * py)) {
2688       continue;
2689     }
2690 
2691     /* If final point is an "edge pixel", use its "real" neighbor instead */
2692     if (tempPoints[final_index].neighbor_pixel != -1) {
2693       final_index = tempPoints[final_index].neighbor_pixel;
2694 
2695       /* If we ended up to our origin point */
2696       if (final_index == (px + w * py)) {
2697         continue;
2698       }
2699     }
2700 
2701     const int final_tri_index = tempPoints[final_index].tri_index;
2702     /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
2703     if (final_tri_index != target_tri && final_tri_index != -1) {
2704       /* Check if it's close enough to likely touch the intended triangle. Any triangle
2705        * becomes thinner than a pixel at its vertices, so robustness requires some margin. */
2706       const float final_pt[2] = {((final_index % w) + 0.5f) / w, ((final_index / w) + 0.5f) / h};
2707       const float threshold = square_f(0.7f) / (w * h);
2708 
2709       if (dist_squared_to_looptri_uv_edges(mlooptri, mloopuv, final_tri_index, final_pt) >
2710           threshold) {
2711         continue;
2712       }
2713     }
2714 
2715     bdata->best_index = final_index;
2716     bdata->best_weight = dist_squared;
2717   }
2718 }
2719 
dynamicPaint_pointHasNeighbor(PaintAdjData * ed,int index,int neighbor)2720 static bool dynamicPaint_pointHasNeighbor(PaintAdjData *ed, int index, int neighbor)
2721 {
2722   const int idx = ed->n_index[index];
2723 
2724   for (int i = 0; i < ed->n_num[index]; i++) {
2725     if (ed->n_target[idx + i] == neighbor) {
2726       return true;
2727     }
2728   }
2729 
2730   return false;
2731 }
2732 
2733 /* Makes the adjacency data symmetric, except for border pixels.
2734  * I.e. if A is neighbor of B, B is neighbor of A. */
dynamicPaint_symmetrizeAdjData(PaintAdjData * ed,int active_points)2735 static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points)
2736 {
2737   int *new_n_index = MEM_callocN(sizeof(int) * active_points, "Surface Adj Index");
2738   int *new_n_num = MEM_callocN(sizeof(int) * active_points, "Surface Adj Counts");
2739 
2740   if (new_n_num && new_n_index) {
2741     /* Count symmetrized neighbors */
2742     int total_targets = 0;
2743 
2744     for (int index = 0; index < active_points; index++) {
2745       total_targets += ed->n_num[index];
2746       new_n_num[index] = ed->n_num[index];
2747     }
2748 
2749     for (int index = 0; index < active_points; index++) {
2750       if (ed->flags[index] & ADJ_BORDER_PIXEL) {
2751         continue;
2752       }
2753 
2754       for (int i = 0, idx = ed->n_index[index]; i < ed->n_num[index]; i++) {
2755         const int target = ed->n_target[idx + i];
2756 
2757         BLI_assert(!(ed->flags[target] & ADJ_BORDER_PIXEL));
2758 
2759         if (!dynamicPaint_pointHasNeighbor(ed, target, index)) {
2760           new_n_num[target]++;
2761           total_targets++;
2762         }
2763       }
2764     }
2765 
2766     /* Allocate a new target map */
2767     int *new_n_target = MEM_callocN(sizeof(int) * total_targets, "Surface Adj Targets");
2768 
2769     if (new_n_target) {
2770       /* Copy existing neighbors to the new map */
2771       int n_pos = 0;
2772 
2773       for (int index = 0; index < active_points; index++) {
2774         new_n_index[index] = n_pos;
2775         memcpy(&new_n_target[n_pos],
2776                &ed->n_target[ed->n_index[index]],
2777                sizeof(int) * ed->n_num[index]);
2778 
2779         /* Reset count to old, but advance position by new, leaving a gap to fill below. */
2780         n_pos += new_n_num[index];
2781         new_n_num[index] = ed->n_num[index];
2782       }
2783 
2784       BLI_assert(n_pos == total_targets);
2785 
2786       /* Add symmetrized - this loop behavior must exactly match the count pass above */
2787       for (int index = 0; index < active_points; index++) {
2788         if (ed->flags[index] & ADJ_BORDER_PIXEL) {
2789           continue;
2790         }
2791 
2792         for (int i = 0, idx = ed->n_index[index]; i < ed->n_num[index]; i++) {
2793           const int target = ed->n_target[idx + i];
2794 
2795           if (!dynamicPaint_pointHasNeighbor(ed, target, index)) {
2796             const int num = new_n_num[target]++;
2797             new_n_target[new_n_index[target] + num] = index;
2798           }
2799         }
2800       }
2801 
2802       /* Swap maps */
2803       MEM_freeN(ed->n_target);
2804       ed->n_target = new_n_target;
2805 
2806       MEM_freeN(ed->n_index);
2807       ed->n_index = new_n_index;
2808 
2809       MEM_freeN(ed->n_num);
2810       ed->n_num = new_n_num;
2811 
2812       ed->total_targets = total_targets;
2813       return true;
2814     }
2815   }
2816 
2817   if (new_n_index) {
2818     MEM_freeN(new_n_index);
2819   }
2820   if (new_n_num) {
2821     MEM_freeN(new_n_num);
2822   }
2823 
2824   return false;
2825 }
2826 
dynamicPaint_createUVSurface(Scene * scene,DynamicPaintSurface * surface,float * progress,short * do_update)2827 int dynamicPaint_createUVSurface(Scene *scene,
2828                                  DynamicPaintSurface *surface,
2829                                  float *progress,
2830                                  short *do_update)
2831 {
2832   /* Antialias jitter point relative coords */
2833   const int aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
2834   char uvname[MAX_CUSTOMDATA_LAYER_NAME];
2835   uint32_t active_points = 0;
2836   bool error = false;
2837 
2838   PaintSurfaceData *sData;
2839   DynamicPaintCanvasSettings *canvas = surface->canvas;
2840   Mesh *mesh = dynamicPaint_canvas_mesh_get(canvas);
2841 
2842   PaintUVPoint *tempPoints = NULL;
2843   Vec3f *tempWeights = NULL;
2844   const MLoopTri *mlooptri = NULL;
2845   const MLoopUV *mloopuv = NULL;
2846   const MLoop *mloop = NULL;
2847 
2848   Bounds2D *faceBB = NULL;
2849   int *final_index;
2850 
2851   *progress = 0.0f;
2852   *do_update = true;
2853 
2854   if (!mesh) {
2855     return setError(canvas, N_("Canvas mesh not updated"));
2856   }
2857   if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) {
2858     return setError(canvas, N_("Cannot bake non-'image sequence' formats"));
2859   }
2860 
2861   mloop = mesh->mloop;
2862   mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
2863   const int tottri = BKE_mesh_runtime_looptri_len(mesh);
2864 
2865   /* get uv map */
2866   if (CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) {
2867     CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, surface->uvlayer_name, uvname);
2868     mloopuv = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvname);
2869   }
2870 
2871   /* Check for validity */
2872   if (!mloopuv) {
2873     return setError(canvas, N_("No UV data on canvas"));
2874   }
2875   if (surface->image_resolution < 16 || surface->image_resolution > 8192) {
2876     return setError(canvas, N_("Invalid resolution"));
2877   }
2878 
2879   const int w = surface->image_resolution;
2880   const int h = w;
2881 
2882   /*
2883    * Start generating the surface
2884    */
2885   CLOG_INFO(&LOG, 1, "Preparing UV surface of %ix%i pixels and %i tris.", w, h, tottri);
2886 
2887   /* Init data struct */
2888   if (surface->data) {
2889     dynamicPaint_freeSurfaceData(surface);
2890   }
2891   sData = surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData");
2892   if (!surface->data) {
2893     return setError(canvas, N_("Not enough free memory"));
2894   }
2895 
2896   tempPoints = MEM_callocN(w * h * sizeof(*tempPoints), "Temp PaintUVPoint");
2897   if (!tempPoints) {
2898     error = true;
2899   }
2900 
2901   final_index = MEM_callocN(w * h * sizeof(*final_index), "Temp UV Final Indexes");
2902   if (!final_index) {
2903     error = true;
2904   }
2905 
2906   tempWeights = MEM_mallocN(w * h * aa_samples * sizeof(*tempWeights), "Temp bWeights");
2907   if (!tempWeights) {
2908     error = true;
2909   }
2910 
2911   /*
2912    * Generate a temporary bounding box array for UV faces to optimize
2913    * the pixel-inside-a-face search.
2914    */
2915   if (!error) {
2916     faceBB = MEM_mallocN(tottri * sizeof(*faceBB), "MPCanvasFaceBB");
2917     if (!faceBB) {
2918       error = true;
2919     }
2920   }
2921 
2922   *progress = 0.01f;
2923   *do_update = true;
2924 
2925   if (!error) {
2926     for (int i = 0; i < tottri; i++) {
2927       copy_v2_v2(faceBB[i].min, mloopuv[mlooptri[i].tri[0]].uv);
2928       copy_v2_v2(faceBB[i].max, mloopuv[mlooptri[i].tri[0]].uv);
2929 
2930       for (int j = 1; j < 3; j++) {
2931         minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[mlooptri[i].tri[j]].uv);
2932       }
2933     }
2934 
2935     *progress = 0.02f;
2936     *do_update = true;
2937 
2938     /* Loop through every pixel and check if pixel is uv-mapped on a canvas face. */
2939     DynamicPaintCreateUVSurfaceData data = {
2940         .surface = surface,
2941         .tempPoints = tempPoints,
2942         .tempWeights = tempWeights,
2943         .mlooptri = mlooptri,
2944         .mloopuv = mloopuv,
2945         .mloop = mloop,
2946         .tottri = tottri,
2947         .faceBB = faceBB,
2948     };
2949     {
2950       TaskParallelSettings settings;
2951       BLI_parallel_range_settings_defaults(&settings);
2952       settings.use_threading = (h > 64 || tottri > 1000);
2953       BLI_task_parallel_range(0, h, &data, dynamic_paint_create_uv_surface_direct_cb, &settings);
2954     }
2955 
2956     *progress = 0.04f;
2957     *do_update = true;
2958 
2959     /*
2960      * Now loop through every pixel that was left without index
2961      * and find if they have neighboring pixels that have an index.
2962      * If so use that polygon as pixel surface.
2963      * (To avoid seams on uv island edges)
2964      */
2965     data.active_points = &active_points;
2966     {
2967       TaskParallelSettings settings;
2968       BLI_parallel_range_settings_defaults(&settings);
2969       settings.use_threading = (h > 64);
2970       BLI_task_parallel_range(0, h, &data, dynamic_paint_create_uv_surface_neighbor_cb, &settings);
2971     }
2972 
2973     *progress = 0.06f;
2974     *do_update = true;
2975 
2976     /* Generate surface adjacency data. */
2977     {
2978       int cursor = 0;
2979 
2980       /* Create a temporary array of final indexes (before unassigned
2981        * pixels have been dropped) */
2982       for (int i = 0; i < w * h; i++) {
2983         if (tempPoints[i].tri_index != -1) {
2984           final_index[i] = cursor;
2985           cursor++;
2986         }
2987       }
2988       /* allocate memory */
2989       sData->total_points = w * h;
2990       dynamicPaint_initAdjacencyData(surface, true);
2991 
2992       if (sData->adj_data) {
2993         PaintAdjData *ed = sData->adj_data;
2994         int n_pos = 0;
2995 
2996         MeshElemMap *vert_to_looptri_map;
2997         int *vert_to_looptri_map_mem;
2998 
2999         BKE_mesh_vert_looptri_map_create(&vert_to_looptri_map,
3000                                          &vert_to_looptri_map_mem,
3001                                          mesh->mvert,
3002                                          mesh->totvert,
3003                                          mlooptri,
3004                                          tottri,
3005                                          mloop,
3006                                          mesh->totloop);
3007 
3008         int total_border = 0;
3009 
3010         for (int ty = 0; ty < h; ty++) {
3011           for (int tx = 0; tx < w; tx++) {
3012             const int index = tx + w * ty;
3013 
3014             if (tempPoints[index].tri_index != -1) {
3015               ed->n_index[final_index[index]] = n_pos;
3016               ed->n_num[final_index[index]] = 0;
3017 
3018               if (tempPoints[index].neighbor_pixel != -1) {
3019                 ed->flags[final_index[index]] |= ADJ_BORDER_PIXEL;
3020                 total_border++;
3021               }
3022 
3023               for (int i = 0; i < 8; i++) {
3024                 /* Try to find a neighboring pixel in defined direction.
3025                  * If not found, -1 is returned */
3026                 const int n_target = dynamic_paint_find_neighbor_pixel(
3027                     &data, vert_to_looptri_map, w, h, tx, ty, i);
3028 
3029                 if (n_target >= 0 && n_target != index) {
3030                   if (!dynamicPaint_pointHasNeighbor(
3031                           ed, final_index[index], final_index[n_target])) {
3032                     ed->n_target[n_pos] = final_index[n_target];
3033                     ed->n_num[final_index[index]]++;
3034                     n_pos++;
3035                   }
3036                 }
3037                 else if (n_target == ON_MESH_EDGE || n_target == OUT_OF_TEXTURE) {
3038                   ed->flags[final_index[index]] |= ADJ_ON_MESH_EDGE;
3039                 }
3040               }
3041             }
3042           }
3043         }
3044 
3045         MEM_freeN(vert_to_looptri_map);
3046         MEM_freeN(vert_to_looptri_map_mem);
3047 
3048         /* Make neighbors symmetric */
3049         if (!dynamicPaint_symmetrizeAdjData(ed, active_points)) {
3050           error = true;
3051         }
3052 
3053         /* Create a list of border pixels */
3054         ed->border = MEM_callocN(sizeof(int) * total_border, "Border Pixel Index");
3055 
3056         if (ed->border) {
3057           ed->total_border = total_border;
3058 
3059           for (int i = 0, next = 0; i < active_points; i++) {
3060             if (ed->flags[i] & ADJ_BORDER_PIXEL) {
3061               ed->border[next++] = i;
3062             }
3063           }
3064         }
3065 
3066 #if 0
3067         /* -----------------------------------------------------------------
3068          * For debug, write a dump of adjacency data to a file.
3069          * -----------------------------------------------------------------*/
3070         FILE *dump_file = fopen("dynpaint-adj-data.txt", "w");
3071         int *tmp = MEM_callocN(sizeof(int) * active_points, "tmp");
3072         for (int ty = 0; ty < h; ty++) {
3073           for (int tx = 0; tx < w; tx++) {
3074             const int index = tx + w * ty;
3075             if (tempPoints[index].tri_index != -1) {
3076               tmp[final_index[index]] = index;
3077             }
3078           }
3079         }
3080         for (int ty = 0; ty < h; ty++) {
3081           for (int tx = 0; tx < w; tx++) {
3082             const int index = tx + w * ty;
3083             const int fidx = final_index[index];
3084 
3085             if (tempPoints[index].tri_index != -1) {
3086               int nidx = tempPoints[index].neighbor_pixel;
3087               fprintf(dump_file,
3088                       "%d\t%d,%d\t%u\t%d,%d\t%d\t",
3089                       fidx,
3090                       tx,
3091                       h - 1 - ty,
3092                       tempPoints[index].tri_index,
3093                       nidx < 0 ? -1 : (nidx % w),
3094                       nidx < 0 ? -1 : h - 1 - (nidx / w),
3095                       ed->flags[fidx]);
3096               for (int i = 0; i < ed->n_num[fidx]; i++) {
3097                 int tgt = tmp[ed->n_target[ed->n_index[fidx] + i]];
3098                 fprintf(dump_file, "%s%d,%d", i ? " " : "", tgt % w, h - 1 - tgt / w);
3099               }
3100               fprintf(dump_file, "\n");
3101             }
3102           }
3103         }
3104         MEM_freeN(tmp);
3105         fclose(dump_file);
3106 #endif
3107       }
3108     }
3109 
3110     *progress = 0.08f;
3111     *do_update = true;
3112 
3113     /* Create final surface data without inactive points */
3114     ImgSeqFormatData *f_data = MEM_callocN(sizeof(*f_data), "ImgSeqFormatData");
3115     if (f_data) {
3116       f_data->uv_p = MEM_callocN(active_points * sizeof(*f_data->uv_p), "PaintUVPoint");
3117       f_data->barycentricWeights = MEM_callocN(
3118           active_points * aa_samples * sizeof(*f_data->barycentricWeights), "PaintUVPoint");
3119 
3120       if (!f_data->uv_p || !f_data->barycentricWeights) {
3121         error = 1;
3122       }
3123     }
3124     else {
3125       error = 1;
3126     }
3127 
3128     /* in case of allocation error, free everything */
3129     if (error) {
3130       if (f_data) {
3131         if (f_data->uv_p) {
3132           MEM_freeN(f_data->uv_p);
3133         }
3134         if (f_data->barycentricWeights) {
3135           MEM_freeN(f_data->barycentricWeights);
3136         }
3137         MEM_freeN(f_data);
3138       }
3139       sData->total_points = 0;
3140     }
3141     else {
3142       sData->total_points = (int)active_points;
3143       sData->format_data = f_data;
3144 
3145       for (int index = 0, cursor = 0; index < (w * h); index++) {
3146         if (tempPoints[index].tri_index != -1) {
3147           memcpy(&f_data->uv_p[cursor], &tempPoints[index], sizeof(PaintUVPoint));
3148           memcpy(&f_data->barycentricWeights[cursor * aa_samples],
3149                  &tempWeights[index * aa_samples],
3150                  sizeof(*tempWeights) * aa_samples);
3151           cursor++;
3152         }
3153       }
3154     }
3155   }
3156   if (error == 1) {
3157     setError(canvas, N_("Not enough free memory"));
3158   }
3159 
3160   if (faceBB) {
3161     MEM_freeN(faceBB);
3162   }
3163   if (tempPoints) {
3164     MEM_freeN(tempPoints);
3165   }
3166   if (tempWeights) {
3167     MEM_freeN(tempWeights);
3168   }
3169   if (final_index) {
3170     MEM_freeN(final_index);
3171   }
3172 
3173   /* Init surface type data */
3174   if (!error) {
3175     dynamicPaint_allocateSurfaceType(surface);
3176 
3177 #if 0
3178     /* -----------------------------------------------------------------
3179      * For debug, output pixel statuses to the color map
3180      * -----------------------------------------------------------------*/
3181     for (index = 0; index < sData->total_points; index++) {
3182       ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
3183       PaintUVPoint *uvPoint = &((PaintUVPoint *)f_data->uv_p)[index];
3184       PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
3185       pPoint->alpha = 1.0f;
3186 
3187       /* Every pixel that is assigned as "edge pixel" gets blue color */
3188       if (uvPoint->neighbor_pixel != -1) {
3189         pPoint->color[2] = 1.0f;
3190       }
3191       /* and every pixel that finally got an polygon gets red color */
3192       /* green color shows pixel face index hash */
3193       if (uvPoint->tri_index != -1) {
3194         pPoint->color[0] = 1.0f;
3195         pPoint->color[1] = (float)(uvPoint->tri_index % 255) / 256.0f;
3196       }
3197     }
3198 #endif
3199 
3200     dynamicPaint_setInitialColor(scene, surface);
3201   }
3202 
3203   *progress = 0.09f;
3204   *do_update = true;
3205 
3206   return (error == 0);
3207 }
3208 
3209 /*
3210  * Outputs an image file from uv surface data.
3211  */
3212 typedef struct DynamicPaintOutputSurfaceImageData {
3213   const DynamicPaintSurface *surface;
3214   ImBuf *ibuf;
3215 } DynamicPaintOutputSurfaceImageData;
3216 
dynamic_paint_output_surface_image_paint_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))3217 static void dynamic_paint_output_surface_image_paint_cb(
3218     void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls))
3219 {
3220   const DynamicPaintOutputSurfaceImageData *data = userdata;
3221 
3222   const DynamicPaintSurface *surface = data->surface;
3223   const PaintPoint *point = &((PaintPoint *)surface->data->type_data)[index];
3224 
3225   ImBuf *ibuf = data->ibuf;
3226   /* image buffer position */
3227   const int pos = ((ImgSeqFormatData *)(surface->data->format_data))->uv_p[index].pixel_index * 4;
3228 
3229   /* blend wet and dry layers */
3230   blendColors(
3231       point->color, point->color[3], point->e_color, point->e_color[3], &ibuf->rect_float[pos]);
3232 
3233   /* Multiply color by alpha if enabled */
3234   if (surface->flags & MOD_DPAINT_MULALPHA) {
3235     mul_v3_fl(&ibuf->rect_float[pos], ibuf->rect_float[pos + 3]);
3236   }
3237 }
3238 
dynamic_paint_output_surface_image_displace_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))3239 static void dynamic_paint_output_surface_image_displace_cb(
3240     void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls))
3241 {
3242   const DynamicPaintOutputSurfaceImageData *data = userdata;
3243 
3244   const DynamicPaintSurface *surface = data->surface;
3245   float depth = ((float *)surface->data->type_data)[index];
3246 
3247   ImBuf *ibuf = data->ibuf;
3248   /* image buffer position */
3249   const int pos = ((ImgSeqFormatData *)(surface->data->format_data))->uv_p[index].pixel_index * 4;
3250 
3251   if (surface->depth_clamp) {
3252     depth /= surface->depth_clamp;
3253   }
3254 
3255   if (surface->disp_type == MOD_DPAINT_DISP_DISPLACE) {
3256     depth = (0.5f - depth / 2.0f);
3257   }
3258 
3259   CLAMP(depth, 0.0f, 1.0f);
3260 
3261   copy_v3_fl(&ibuf->rect_float[pos], depth);
3262   ibuf->rect_float[pos + 3] = 1.0f;
3263 }
3264 
dynamic_paint_output_surface_image_wave_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))3265 static void dynamic_paint_output_surface_image_wave_cb(
3266     void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls))
3267 {
3268   const DynamicPaintOutputSurfaceImageData *data = userdata;
3269 
3270   const DynamicPaintSurface *surface = data->surface;
3271   const PaintWavePoint *wPoint = &((PaintWavePoint *)surface->data->type_data)[index];
3272   float depth = wPoint->height;
3273 
3274   ImBuf *ibuf = data->ibuf;
3275   /* image buffer position */
3276   const int pos = ((ImgSeqFormatData *)(surface->data->format_data))->uv_p[index].pixel_index * 4;
3277 
3278   if (surface->depth_clamp) {
3279     depth /= surface->depth_clamp;
3280   }
3281 
3282   depth = (0.5f + depth / 2.0f);
3283   CLAMP(depth, 0.0f, 1.0f);
3284 
3285   copy_v3_fl(&ibuf->rect_float[pos], depth);
3286   ibuf->rect_float[pos + 3] = 1.0f;
3287 }
3288 
dynamic_paint_output_surface_image_wetmap_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))3289 static void dynamic_paint_output_surface_image_wetmap_cb(
3290     void *__restrict userdata, const int index, const TaskParallelTLS *__restrict UNUSED(tls))
3291 {
3292   const DynamicPaintOutputSurfaceImageData *data = userdata;
3293 
3294   const DynamicPaintSurface *surface = data->surface;
3295   const PaintPoint *point = &((PaintPoint *)surface->data->type_data)[index];
3296 
3297   ImBuf *ibuf = data->ibuf;
3298   /* image buffer position */
3299   const int pos = ((ImgSeqFormatData *)(surface->data->format_data))->uv_p[index].pixel_index * 4;
3300 
3301   copy_v3_fl(&ibuf->rect_float[pos], (point->wetness > 1.0f) ? 1.0f : point->wetness);
3302   ibuf->rect_float[pos + 3] = 1.0f;
3303 }
3304 
dynamicPaint_outputSurfaceImage(DynamicPaintSurface * surface,char * filename,short output_layer)3305 void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface,
3306                                      char *filename,
3307                                      short output_layer)
3308 {
3309   ImBuf *ibuf = NULL;
3310   PaintSurfaceData *sData = surface->data;
3311   /* OpenEXR or PNG */
3312   int format = (surface->image_fileformat & MOD_DPAINT_IMGFORMAT_OPENEXR) ? R_IMF_IMTYPE_OPENEXR :
3313                                                                             R_IMF_IMTYPE_PNG;
3314   char output_file[FILE_MAX];
3315 
3316   if (!sData->type_data) {
3317     setError(surface->canvas, N_("Image save failed: invalid surface"));
3318     return;
3319   }
3320   /* if selected format is openexr, but current build doesn't support one */
3321 #ifndef WITH_OPENEXR
3322   if (format == R_IMF_IMTYPE_OPENEXR) {
3323     format = R_IMF_IMTYPE_PNG;
3324   }
3325 #endif
3326   BLI_strncpy(output_file, filename, sizeof(output_file));
3327   BKE_image_path_ensure_ext_from_imtype(output_file, format);
3328 
3329   /* Validate output file path */
3330   BLI_path_abs(output_file, BKE_main_blendfile_path_from_global());
3331   BLI_make_existing_file(output_file);
3332 
3333   /* Init image buffer */
3334   ibuf = IMB_allocImBuf(surface->image_resolution, surface->image_resolution, 32, IB_rectfloat);
3335   if (ibuf == NULL) {
3336     setError(surface->canvas, N_("Image save failed: not enough free memory"));
3337     return;
3338   }
3339 
3340   DynamicPaintOutputSurfaceImageData data = {
3341       .surface = surface,
3342       .ibuf = ibuf,
3343   };
3344   switch (surface->type) {
3345     case MOD_DPAINT_SURFACE_T_PAINT:
3346       switch (output_layer) {
3347         case 0: {
3348           TaskParallelSettings settings;
3349           BLI_parallel_range_settings_defaults(&settings);
3350           settings.use_threading = (sData->total_points > 10000);
3351           BLI_task_parallel_range(0,
3352                                   sData->total_points,
3353                                   &data,
3354                                   dynamic_paint_output_surface_image_paint_cb,
3355                                   &settings);
3356           break;
3357         }
3358         case 1: {
3359           TaskParallelSettings settings;
3360           BLI_parallel_range_settings_defaults(&settings);
3361           settings.use_threading = (sData->total_points > 10000);
3362           BLI_task_parallel_range(0,
3363                                   sData->total_points,
3364                                   &data,
3365                                   dynamic_paint_output_surface_image_wetmap_cb,
3366                                   &settings);
3367           break;
3368         }
3369         default:
3370           BLI_assert(0);
3371           break;
3372       }
3373       break;
3374     case MOD_DPAINT_SURFACE_T_DISPLACE:
3375       switch (output_layer) {
3376         case 0: {
3377           TaskParallelSettings settings;
3378           BLI_parallel_range_settings_defaults(&settings);
3379           settings.use_threading = (sData->total_points > 10000);
3380           BLI_task_parallel_range(0,
3381                                   sData->total_points,
3382                                   &data,
3383                                   dynamic_paint_output_surface_image_displace_cb,
3384                                   &settings);
3385           break;
3386         }
3387         case 1:
3388           break;
3389         default:
3390           BLI_assert(0);
3391           break;
3392       }
3393       break;
3394     case MOD_DPAINT_SURFACE_T_WAVE:
3395       switch (output_layer) {
3396         case 0: {
3397           TaskParallelSettings settings;
3398           BLI_parallel_range_settings_defaults(&settings);
3399           settings.use_threading = (sData->total_points > 10000);
3400           BLI_task_parallel_range(0,
3401                                   sData->total_points,
3402                                   &data,
3403                                   dynamic_paint_output_surface_image_wave_cb,
3404                                   &settings);
3405           break;
3406         }
3407         case 1:
3408           break;
3409         default:
3410           BLI_assert(0);
3411           break;
3412       }
3413       break;
3414     default:
3415       BLI_assert(0);
3416       break;
3417   }
3418 
3419     /* Set output format, png in case exr isn't supported */
3420 #ifdef WITH_OPENEXR
3421   if (format == R_IMF_IMTYPE_OPENEXR) { /* OpenEXR 32-bit float */
3422     ibuf->ftype = IMB_FTYPE_OPENEXR;
3423     ibuf->foptions.flag |= OPENEXR_COMPRESS;
3424   }
3425   else
3426 #endif
3427   {
3428     ibuf->ftype = IMB_FTYPE_PNG;
3429     ibuf->foptions.quality = 15;
3430   }
3431 
3432   /* Save image */
3433   IMB_saveiff(ibuf, output_file, IB_rectfloat);
3434   IMB_freeImBuf(ibuf);
3435 }
3436 
3437 /** \} */
3438 
3439 /***************************** Ray / Nearest Point Utils ******************************/
3440 
3441 /* A modified callback to bvh tree raycast.
3442  * The tree must have been built using bvhtree_from_mesh_looptri.
3443  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
3444  *
3445  * To optimize brush detection speed this doesn't calculate hit coordinates or normal.
3446  */
mesh_tris_spherecast_dp(void * userdata,int index,const BVHTreeRay * ray,BVHTreeRayHit * hit)3447 static void mesh_tris_spherecast_dp(void *userdata,
3448                                     int index,
3449                                     const BVHTreeRay *ray,
3450                                     BVHTreeRayHit *hit)
3451 {
3452   const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
3453   const MVert *vert = data->vert;
3454   const MLoopTri *mlooptri = data->looptri;
3455   const MLoop *mloop = data->loop;
3456 
3457   const float *t0, *t1, *t2;
3458   float dist;
3459 
3460   t0 = vert[mloop[mlooptri[index].tri[0]].v].co;
3461   t1 = vert[mloop[mlooptri[index].tri[1]].v].co;
3462   t2 = vert[mloop[mlooptri[index].tri[2]].v].co;
3463 
3464   dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
3465 
3466   if (dist >= 0 && dist < hit->dist) {
3467     hit->index = index;
3468     hit->dist = dist;
3469     hit->no[0] = 0.0f;
3470   }
3471 }
3472 
3473 /* A modified callback to bvh tree nearest point.
3474  * The tree must have been built using bvhtree_from_mesh_looptri.
3475  * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree.
3476  *
3477  * To optimize brush detection speed this doesn't calculate hit normal.
3478  */
mesh_tris_nearest_point_dp(void * userdata,int index,const float co[3],BVHTreeNearest * nearest)3479 static void mesh_tris_nearest_point_dp(void *userdata,
3480                                        int index,
3481                                        const float co[3],
3482                                        BVHTreeNearest *nearest)
3483 {
3484   const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
3485   const MVert *vert = data->vert;
3486   const MLoopTri *mlooptri = data->looptri;
3487   const MLoop *mloop = data->loop;
3488   float nearest_tmp[3], dist_sq;
3489 
3490   const float *t0, *t1, *t2;
3491   t0 = vert[mloop[mlooptri[index].tri[0]].v].co;
3492   t1 = vert[mloop[mlooptri[index].tri[1]].v].co;
3493   t2 = vert[mloop[mlooptri[index].tri[2]].v].co;
3494 
3495   closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
3496   dist_sq = len_squared_v3v3(co, nearest_tmp);
3497 
3498   if (dist_sq < nearest->dist_sq) {
3499     nearest->index = index;
3500     nearest->dist_sq = dist_sq;
3501     copy_v3_v3(nearest->co, nearest_tmp);
3502     nearest->no[0] = 0.0f;
3503   }
3504 }
3505 
3506 /***************************** Brush Painting Calls ******************************/
3507 
3508 /**
3509  * Mix color values to canvas point.
3510  *
3511  * \param surface: Canvas surface
3512  * \param index: Surface point index
3513  * \param paintFlags: paint object flags
3514  * \param paintColor,paintAlpha,paintWetness: To be mixed paint values
3515  * \param timescale: Value used to adjust time dependent
3516  * operations when using substeps
3517  */
dynamicPaint_mixPaintColors(const DynamicPaintSurface * surface,const int index,const int paintFlags,const float paintColor[3],const float paintAlpha,const float paintWetness,const float timescale)3518 static void dynamicPaint_mixPaintColors(const DynamicPaintSurface *surface,
3519                                         const int index,
3520                                         const int paintFlags,
3521                                         const float paintColor[3],
3522                                         const float paintAlpha,
3523                                         const float paintWetness,
3524                                         const float timescale)
3525 {
3526   PaintPoint *pPoint = &((PaintPoint *)surface->data->type_data)[index];
3527 
3528   /* Add paint */
3529   if (!(paintFlags & MOD_DPAINT_ERASE)) {
3530     float mix[4];
3531     float temp_alpha = paintAlpha * ((paintFlags & MOD_DPAINT_ABS_ALPHA) ? 1.0f : timescale);
3532 
3533     /* mix brush color with wet layer color */
3534     blendColors(pPoint->e_color, pPoint->e_color[3], paintColor, temp_alpha, mix);
3535     copy_v3_v3(pPoint->e_color, mix);
3536 
3537     /* mix wetness and alpha depending on selected alpha mode */
3538     if (paintFlags & MOD_DPAINT_ABS_ALPHA) {
3539       /* update values to the brush level unless they're higher already */
3540       CLAMP_MIN(pPoint->e_color[3], paintAlpha);
3541       CLAMP_MIN(pPoint->wetness, paintWetness);
3542     }
3543     else {
3544       float wetness = paintWetness;
3545       CLAMP(wetness, 0.0f, 1.0f);
3546       pPoint->e_color[3] = mix[3];
3547       pPoint->wetness = pPoint->wetness * (1.0f - wetness) + wetness;
3548     }
3549 
3550     CLAMP_MIN(pPoint->wetness, MIN_WETNESS);
3551 
3552     pPoint->state = DPAINT_PAINT_NEW;
3553   }
3554   /* Erase paint */
3555   else {
3556     float a_ratio, a_highest;
3557     float wetness;
3558     float invFact = 1.0f - paintAlpha;
3559 
3560     /*
3561      * Make highest alpha to match erased value
3562      * but maintain alpha ratio
3563      */
3564     if (paintFlags & MOD_DPAINT_ABS_ALPHA) {
3565       a_highest = max_ff(pPoint->color[3], pPoint->e_color[3]);
3566       if (a_highest > invFact) {
3567         a_ratio = invFact / a_highest;
3568 
3569         pPoint->e_color[3] *= a_ratio;
3570         pPoint->color[3] *= a_ratio;
3571       }
3572     }
3573     else {
3574       pPoint->e_color[3] -= paintAlpha * timescale;
3575       CLAMP_MIN(pPoint->e_color[3], 0.0f);
3576       pPoint->color[3] -= paintAlpha * timescale;
3577       CLAMP_MIN(pPoint->color[3], 0.0f);
3578     }
3579 
3580     wetness = (1.0f - paintWetness) * pPoint->e_color[3];
3581     CLAMP_MAX(pPoint->wetness, wetness);
3582   }
3583 }
3584 
3585 /* applies given brush intersection value for wave surface */
dynamicPaint_mixWaveHeight(PaintWavePoint * wPoint,const DynamicPaintBrushSettings * brush,float isect_height)3586 static void dynamicPaint_mixWaveHeight(PaintWavePoint *wPoint,
3587                                        const DynamicPaintBrushSettings *brush,
3588                                        float isect_height)
3589 {
3590   const float isect_change = isect_height - wPoint->brush_isect;
3591   const float wave_factor = brush->wave_factor;
3592   bool hit = false;
3593 
3594   /* intersection marked regardless of brush type or hit */
3595   wPoint->brush_isect = isect_height;
3596   wPoint->state = DPAINT_WAVE_ISECT_CHANGED;
3597 
3598   isect_height *= wave_factor;
3599 
3600   /* determine hit depending on wave_factor */
3601   if (wave_factor > 0.0f && wPoint->height > isect_height) {
3602     hit = true;
3603   }
3604   else if (wave_factor < 0.0f && wPoint->height < isect_height) {
3605     hit = true;
3606   }
3607 
3608   if (hit) {
3609     switch (brush->wave_type) {
3610       case MOD_DPAINT_WAVEB_DEPTH:
3611         wPoint->height = isect_height;
3612         wPoint->state = DPAINT_WAVE_OBSTACLE;
3613         wPoint->velocity = 0.0f;
3614         break;
3615       case MOD_DPAINT_WAVEB_FORCE:
3616         wPoint->velocity = isect_height;
3617         break;
3618       case MOD_DPAINT_WAVEB_REFLECT:
3619         wPoint->state = DPAINT_WAVE_REFLECT_ONLY;
3620         break;
3621       case MOD_DPAINT_WAVEB_CHANGE:
3622         if (isect_change < 0.0f) {
3623           wPoint->height += isect_change * wave_factor;
3624         }
3625         break;
3626       default:
3627         BLI_assert(0);
3628         break;
3629     }
3630   }
3631 }
3632 
3633 /*
3634  * add brush results to the surface data depending on surface type
3635  */
dynamicPaint_updatePointData(const DynamicPaintSurface * surface,const int index,const DynamicPaintBrushSettings * brush,float paint[3],float influence,float depth,float vel_factor,const float timescale)3636 static void dynamicPaint_updatePointData(const DynamicPaintSurface *surface,
3637                                          const int index,
3638                                          const DynamicPaintBrushSettings *brush,
3639                                          float paint[3],
3640                                          float influence,
3641                                          float depth,
3642                                          float vel_factor,
3643                                          const float timescale)
3644 {
3645   PaintSurfaceData *sData = surface->data;
3646   float strength;
3647 
3648   /* apply influence scale */
3649   influence *= surface->influence_scale;
3650   depth *= surface->influence_scale;
3651 
3652   strength = influence * brush->alpha;
3653   CLAMP(strength, 0.0f, 1.0f);
3654 
3655   /* Sample velocity colorband if required */
3656   if (brush->flags &
3657       (MOD_DPAINT_VELOCITY_ALPHA | MOD_DPAINT_VELOCITY_COLOR | MOD_DPAINT_VELOCITY_DEPTH)) {
3658     float coba_res[4];
3659     vel_factor /= brush->max_velocity;
3660     CLAMP(vel_factor, 0.0f, 1.0f);
3661 
3662     if (BKE_colorband_evaluate(brush->vel_ramp, vel_factor, coba_res)) {
3663       if (brush->flags & MOD_DPAINT_VELOCITY_COLOR) {
3664         copy_v3_v3(paint, coba_res);
3665       }
3666       if (brush->flags & MOD_DPAINT_VELOCITY_ALPHA) {
3667         strength *= coba_res[3];
3668       }
3669       if (brush->flags & MOD_DPAINT_VELOCITY_DEPTH) {
3670         depth *= coba_res[3];
3671       }
3672     }
3673   }
3674 
3675   /* mix paint surface */
3676   if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
3677     float paintWetness = brush->wetness * strength;
3678     float paintAlpha = strength;
3679 
3680     dynamicPaint_mixPaintColors(
3681         surface, index, brush->flags, paint, paintAlpha, paintWetness, timescale);
3682   }
3683   /* displace surface */
3684   else if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
3685     float *value = (float *)sData->type_data;
3686 
3687     if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL) {
3688       depth = value[index] + depth;
3689     }
3690 
3691     if (surface->depth_clamp) {
3692       CLAMP(depth, 0.0f - surface->depth_clamp, surface->depth_clamp);
3693     }
3694 
3695     if (brush->flags & MOD_DPAINT_ERASE) {
3696       value[index] *= (1.0f - strength);
3697       CLAMP_MIN(value[index], 0.0f);
3698     }
3699     else {
3700       CLAMP_MIN(value[index], depth);
3701     }
3702   }
3703   /* vertex weight group surface */
3704   else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
3705     float *value = (float *)sData->type_data;
3706 
3707     if (brush->flags & MOD_DPAINT_ERASE) {
3708       value[index] *= (1.0f - strength);
3709       CLAMP_MIN(value[index], 0.0f);
3710     }
3711     else {
3712       CLAMP_MIN(value[index], strength);
3713     }
3714   }
3715   /* wave surface */
3716   else if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
3717     if (brush->wave_clamp) {
3718       CLAMP(depth, 0.0f - brush->wave_clamp, brush->wave_clamp);
3719     }
3720 
3721     dynamicPaint_mixWaveHeight(&((PaintWavePoint *)sData->type_data)[index], brush, 0.0f - depth);
3722   }
3723 
3724   /* doing velocity based painting */
3725   if (sData->bData->brush_velocity) {
3726     sData->bData->brush_velocity[index * 4 + 3] *= influence;
3727   }
3728 }
3729 
3730 /* checks whether surface and brush bounds intersect depending on brush type */
meshBrush_boundsIntersect(Bounds3D * b1,Bounds3D * b2,DynamicPaintBrushSettings * brush,float brush_radius)3731 static bool meshBrush_boundsIntersect(Bounds3D *b1,
3732                                       Bounds3D *b2,
3733                                       DynamicPaintBrushSettings *brush,
3734                                       float brush_radius)
3735 {
3736   if (brush->collision == MOD_DPAINT_COL_VOLUME) {
3737     return boundsIntersect(b1, b2);
3738   }
3739   if (brush->collision == MOD_DPAINT_COL_DIST || brush->collision == MOD_DPAINT_COL_VOLDIST) {
3740     return boundsIntersectDist(b1, b2, brush_radius);
3741   }
3742   return true;
3743 }
3744 
3745 /* calculate velocity for mesh vertices */
3746 typedef struct DynamicPaintBrushVelocityData {
3747   Vec3f *brush_vel;
3748 
3749   const MVert *mvert_p;
3750   const MVert *mvert_c;
3751 
3752   float (*obmat)[4];
3753   float (*prev_obmat)[4];
3754 
3755   const float timescale;
3756 } DynamicPaintBrushVelocityData;
3757 
dynamic_paint_brush_velocity_compute_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))3758 static void dynamic_paint_brush_velocity_compute_cb(void *__restrict userdata,
3759                                                     const int i,
3760                                                     const TaskParallelTLS *__restrict UNUSED(tls))
3761 {
3762   const DynamicPaintBrushVelocityData *data = userdata;
3763 
3764   Vec3f *brush_vel = data->brush_vel;
3765 
3766   const MVert *mvert_p = data->mvert_p;
3767   const MVert *mvert_c = data->mvert_c;
3768 
3769   float(*obmat)[4] = data->obmat;
3770   float(*prev_obmat)[4] = data->prev_obmat;
3771 
3772   const float timescale = data->timescale;
3773 
3774   float p1[3], p2[3];
3775 
3776   copy_v3_v3(p1, mvert_p[i].co);
3777   mul_m4_v3(prev_obmat, p1);
3778 
3779   copy_v3_v3(p2, mvert_c[i].co);
3780   mul_m4_v3(obmat, p2);
3781 
3782   sub_v3_v3v3(brush_vel[i].v, p2, p1);
3783   mul_v3_fl(brush_vel[i].v, 1.0f / timescale);
3784 }
3785 
dynamicPaint_brushMeshCalculateVelocity(Depsgraph * depsgraph,Scene * scene,Object * ob,DynamicPaintBrushSettings * brush,Vec3f ** brushVel,float timescale)3786 static void dynamicPaint_brushMeshCalculateVelocity(Depsgraph *depsgraph,
3787                                                     Scene *scene,
3788                                                     Object *ob,
3789                                                     DynamicPaintBrushSettings *brush,
3790                                                     Vec3f **brushVel,
3791                                                     float timescale)
3792 {
3793   float prev_obmat[4][4];
3794   Mesh *mesh_p, *mesh_c;
3795   MVert *mvert_p, *mvert_c;
3796   int numOfVerts_p, numOfVerts_c;
3797 
3798   float cur_sfra = scene->r.subframe;
3799   int cur_fra = scene->r.cfra;
3800   float prev_sfra = cur_sfra - timescale;
3801   int prev_fra = cur_fra;
3802 
3803   if (prev_sfra < 0.0f) {
3804     prev_sfra += 1.0f;
3805     prev_fra = cur_fra - 1;
3806   }
3807 
3808   /* previous frame mesh */
3809   scene->r.cfra = prev_fra;
3810   scene->r.subframe = prev_sfra;
3811 
3812   BKE_object_modifier_update_subframe(depsgraph,
3813                                       scene,
3814                                       ob,
3815                                       true,
3816                                       SUBFRAME_RECURSION,
3817                                       BKE_scene_frame_get(scene),
3818                                       eModifierType_DynamicPaint);
3819   mesh_p = BKE_mesh_copy_for_eval(dynamicPaint_brush_mesh_get(brush), false);
3820   numOfVerts_p = mesh_p->totvert;
3821   mvert_p = mesh_p->mvert;
3822   copy_m4_m4(prev_obmat, ob->obmat);
3823 
3824   /* current frame mesh */
3825   scene->r.cfra = cur_fra;
3826   scene->r.subframe = cur_sfra;
3827 
3828   BKE_object_modifier_update_subframe(depsgraph,
3829                                       scene,
3830                                       ob,
3831                                       true,
3832                                       SUBFRAME_RECURSION,
3833                                       BKE_scene_frame_get(scene),
3834                                       eModifierType_DynamicPaint);
3835   mesh_c = dynamicPaint_brush_mesh_get(brush);
3836   numOfVerts_c = mesh_c->totvert;
3837   mvert_c = mesh_c->mvert;
3838 
3839   (*brushVel) = (struct Vec3f *)MEM_mallocN(numOfVerts_c * sizeof(Vec3f),
3840                                             "Dynamic Paint brush velocity");
3841   if (!(*brushVel)) {
3842     return;
3843   }
3844 
3845   /* if mesh is constructive -> num of verts has changed, only use current frame derived mesh */
3846   if (numOfVerts_p != numOfVerts_c) {
3847     mvert_p = mvert_c;
3848   }
3849 
3850   /* calculate speed */
3851   DynamicPaintBrushVelocityData data = {
3852       .brush_vel = *brushVel,
3853       .mvert_p = mvert_p,
3854       .mvert_c = mvert_c,
3855       .obmat = ob->obmat,
3856       .prev_obmat = prev_obmat,
3857       .timescale = timescale,
3858   };
3859   TaskParallelSettings settings;
3860   BLI_parallel_range_settings_defaults(&settings);
3861   settings.use_threading = (numOfVerts_c > 10000);
3862   BLI_task_parallel_range(
3863       0, numOfVerts_c, &data, dynamic_paint_brush_velocity_compute_cb, &settings);
3864 
3865   BKE_id_free(NULL, mesh_p);
3866 }
3867 
3868 /* calculate velocity for object center point */
dynamicPaint_brushObjectCalculateVelocity(Depsgraph * depsgraph,Scene * scene,Object * ob,Vec3f * brushVel,float timescale)3869 static void dynamicPaint_brushObjectCalculateVelocity(
3870     Depsgraph *depsgraph, Scene *scene, Object *ob, Vec3f *brushVel, float timescale)
3871 {
3872   float prev_obmat[4][4];
3873   float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f};
3874 
3875   float cur_sfra = scene->r.subframe;
3876   int cur_fra = scene->r.cfra;
3877   float prev_sfra = cur_sfra - timescale;
3878   int prev_fra = cur_fra;
3879 
3880   if (prev_sfra < 0.0f) {
3881     prev_sfra += 1.0f;
3882     prev_fra = cur_fra - 1;
3883   }
3884 
3885   /* previous frame mesh */
3886   scene->r.cfra = prev_fra;
3887   scene->r.subframe = prev_sfra;
3888   BKE_object_modifier_update_subframe(depsgraph,
3889                                       scene,
3890                                       ob,
3891                                       false,
3892                                       SUBFRAME_RECURSION,
3893                                       BKE_scene_frame_get(scene),
3894                                       eModifierType_DynamicPaint);
3895   copy_m4_m4(prev_obmat, ob->obmat);
3896 
3897   /* current frame mesh */
3898   scene->r.cfra = cur_fra;
3899   scene->r.subframe = cur_sfra;
3900   BKE_object_modifier_update_subframe(depsgraph,
3901                                       scene,
3902                                       ob,
3903                                       false,
3904                                       SUBFRAME_RECURSION,
3905                                       BKE_scene_frame_get(scene),
3906                                       eModifierType_DynamicPaint);
3907 
3908   /* calculate speed */
3909   mul_m4_v3(prev_obmat, prev_loc);
3910   mul_m4_v3(ob->obmat, cur_loc);
3911 
3912   sub_v3_v3v3(brushVel->v, cur_loc, prev_loc);
3913   mul_v3_fl(brushVel->v, 1.0f / timescale);
3914 }
3915 
3916 typedef struct DynamicPaintPaintData {
3917   const DynamicPaintSurface *surface;
3918   const DynamicPaintBrushSettings *brush;
3919   Object *brushOb;
3920   const Scene *scene;
3921   const float timescale;
3922   const int c_index;
3923 
3924   Mesh *mesh;
3925   const MVert *mvert;
3926   const MLoop *mloop;
3927   const MLoopTri *mlooptri;
3928   const float brush_radius;
3929   const float *avg_brushNor;
3930   const Vec3f *brushVelocity;
3931 
3932   const ParticleSystem *psys;
3933   const float solidradius;
3934 
3935   void *treeData;
3936 
3937   float *pointCoord;
3938 } DynamicPaintPaintData;
3939 
3940 /*
3941  * Paint a brush object mesh to the surface
3942  */
dynamic_paint_paint_mesh_cell_point_cb_ex(void * __restrict userdata,const int id,const TaskParallelTLS * __restrict UNUSED (tls))3943 static void dynamic_paint_paint_mesh_cell_point_cb_ex(
3944     void *__restrict userdata, const int id, const TaskParallelTLS *__restrict UNUSED(tls))
3945 {
3946   const DynamicPaintPaintData *data = userdata;
3947 
3948   const DynamicPaintSurface *surface = data->surface;
3949   const PaintSurfaceData *sData = surface->data;
3950   const PaintBakeData *bData = sData->bData;
3951   VolumeGrid *grid = bData->grid;
3952 
3953   const DynamicPaintBrushSettings *brush = data->brush;
3954 
3955   const float timescale = data->timescale;
3956   const int c_index = data->c_index;
3957 
3958   const MVert *mvert = data->mvert;
3959   const MLoop *mloop = data->mloop;
3960   const MLoopTri *mlooptri = data->mlooptri;
3961   const float brush_radius = data->brush_radius;
3962   const float *avg_brushNor = data->avg_brushNor;
3963   const Vec3f *brushVelocity = data->brushVelocity;
3964 
3965   BVHTreeFromMesh *treeData = data->treeData;
3966 
3967   const int index = grid->t_index[grid->s_pos[c_index] + id];
3968   const int samples = bData->s_num[index];
3969   int ss;
3970   float total_sample = (float)samples;
3971   float brushStrength = 0.0f; /* brush influence factor */
3972   float depth = 0.0f;         /* brush intersection depth */
3973   float velocity_val = 0.0f;
3974 
3975   float paintColor[3] = {0.0f};
3976   int numOfHits = 0;
3977 
3978   /* for image sequence anti-aliasing, use gaussian factors */
3979   if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
3980     total_sample = gaussianTotal;
3981   }
3982 
3983   /* Supersampling */
3984   for (ss = 0; ss < samples; ss++) {
3985     float ray_start[3], ray_dir[3];
3986     float sample_factor = 0.0f;
3987     float sampleStrength = 0.0f;
3988     BVHTreeRayHit hit;
3989     BVHTreeNearest nearest;
3990     short hit_found = 0;
3991 
3992     /* volume sample */
3993     float volume_factor = 0.0f;
3994     /* proximity sample */
3995     float proximity_factor = 0.0f;
3996     float prox_colorband[4] = {0.0f};
3997     const bool inner_proximity = (brush->flags & MOD_DPAINT_INVERSE_PROX &&
3998                                   brush->collision == MOD_DPAINT_COL_VOLDIST);
3999 
4000     /* hit data */
4001     float hitCoord[3];
4002     int hitTri = -1;
4003 
4004     /* Supersampling factor */
4005     if (samples > 1 && surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
4006       sample_factor = gaussianFactors[ss];
4007     }
4008     else {
4009       sample_factor = 1.0f;
4010     }
4011 
4012     /* Get current sample position in world coordinates */
4013     copy_v3_v3(ray_start, bData->realCoord[bData->s_pos[index] + ss].v);
4014     copy_v3_v3(ray_dir, bData->bNormal[index].invNorm);
4015 
4016     /* a simple hack to minimize chance of ray leaks at identical ray <-> edge locations */
4017     add_v3_fl(ray_start, 0.001f);
4018 
4019     hit.index = -1;
4020     hit.dist = BVH_RAYCAST_DIST_MAX;
4021     nearest.index = -1;
4022     nearest.dist_sq = brush_radius * brush_radius; /* find_nearest uses squared distance */
4023 
4024     /* Check volume collision */
4025     if (ELEM(brush->collision, MOD_DPAINT_COL_VOLUME, MOD_DPAINT_COL_VOLDIST)) {
4026       BLI_bvhtree_ray_cast(
4027           treeData->tree, ray_start, ray_dir, 0.0f, &hit, mesh_tris_spherecast_dp, treeData);
4028       if (hit.index != -1) {
4029         /* We hit a triangle, now check if collision point normal is facing the point */
4030 
4031         /* For optimization sake, hit point normal isn't calculated in ray cast loop */
4032         const int vtri[3] = {
4033             mloop[mlooptri[hit.index].tri[0]].v,
4034             mloop[mlooptri[hit.index].tri[1]].v,
4035             mloop[mlooptri[hit.index].tri[2]].v,
4036         };
4037         float dot;
4038 
4039         normal_tri_v3(hit.no, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co);
4040         dot = dot_v3v3(ray_dir, hit.no);
4041 
4042         /* If ray and hit face normal are facing same direction
4043          * hit point is inside a closed mesh. */
4044         if (dot >= 0.0f) {
4045           const float dist = hit.dist;
4046           const int f_index = hit.index;
4047 
4048           /* Also cast a ray in opposite direction to make sure
4049            * point is at least surrounded by two brush faces */
4050           negate_v3(ray_dir);
4051           hit.index = -1;
4052           hit.dist = BVH_RAYCAST_DIST_MAX;
4053 
4054           BLI_bvhtree_ray_cast(
4055               treeData->tree, ray_start, ray_dir, 0.0f, &hit, mesh_tris_spherecast_dp, treeData);
4056 
4057           if (hit.index != -1) {
4058             /* Add factor on supersample filter */
4059             volume_factor = 1.0f;
4060             hit_found = HIT_VOLUME;
4061 
4062             /* Mark hit info */
4063 
4064             /* Calculate final hit coordinates */
4065             madd_v3_v3v3fl(hitCoord, ray_start, ray_dir, hit.dist);
4066 
4067             depth += dist * sample_factor;
4068             hitTri = f_index;
4069           }
4070         }
4071       }
4072     }
4073 
4074     /* Check proximity collision */
4075     if (ELEM(brush->collision, MOD_DPAINT_COL_DIST, MOD_DPAINT_COL_VOLDIST) &&
4076         (!hit_found || (brush->flags & MOD_DPAINT_INVERSE_PROX))) {
4077       float proxDist = -1.0f;
4078       float hitCo[3] = {0.0f, 0.0f, 0.0f};
4079       int tri = 0;
4080 
4081       /* if inverse prox and no hit found, skip this sample */
4082       if (inner_proximity && !hit_found) {
4083         continue;
4084       }
4085 
4086       /* If pure distance proximity, find the nearest point on the mesh */
4087       if (!(brush->flags & MOD_DPAINT_PROX_PROJECT)) {
4088         BLI_bvhtree_find_nearest(
4089             treeData->tree, ray_start, &nearest, mesh_tris_nearest_point_dp, treeData);
4090         if (nearest.index != -1) {
4091           proxDist = sqrtf(nearest.dist_sq);
4092           copy_v3_v3(hitCo, nearest.co);
4093           tri = nearest.index;
4094         }
4095       }
4096       else { /* else cast a ray in defined projection direction */
4097         float proj_ray[3] = {0.0f};
4098 
4099         if (brush->ray_dir == MOD_DPAINT_RAY_CANVAS) {
4100           copy_v3_v3(proj_ray, bData->bNormal[index].invNorm);
4101           negate_v3(proj_ray);
4102         }
4103         else if (brush->ray_dir == MOD_DPAINT_RAY_BRUSH_AVG) {
4104           copy_v3_v3(proj_ray, avg_brushNor);
4105         }
4106         else { /* MOD_DPAINT_RAY_ZPLUS */
4107           proj_ray[2] = 1.0f;
4108         }
4109         hit.index = -1;
4110         hit.dist = brush_radius;
4111 
4112         /* Do a face normal directional raycast, and use that distance */
4113         BLI_bvhtree_ray_cast(
4114             treeData->tree, ray_start, proj_ray, 0.0f, &hit, mesh_tris_spherecast_dp, treeData);
4115         if (hit.index != -1) {
4116           proxDist = hit.dist;
4117 
4118           /* Calculate final hit coordinates */
4119           madd_v3_v3v3fl(hitCo, ray_start, proj_ray, hit.dist);
4120 
4121           tri = hit.index;
4122         }
4123       }
4124 
4125       /* If a hit was found, calculate required values */
4126       if (proxDist >= 0.0f && proxDist <= brush_radius) {
4127         proximity_factor = proxDist / brush_radius;
4128         CLAMP(proximity_factor, 0.0f, 1.0f);
4129         if (!inner_proximity) {
4130           proximity_factor = 1.0f - proximity_factor;
4131         }
4132 
4133         hit_found = HIT_PROXIMITY;
4134 
4135         /* if no volume hit, use prox point face info */
4136         if (hitTri == -1) {
4137           copy_v3_v3(hitCoord, hitCo);
4138           hitTri = tri;
4139         }
4140       }
4141     }
4142 
4143     /* mix final sample strength depending on brush settings */
4144     if (hit_found) {
4145       /* if "negate volume" enabled, negate all factors within volume*/
4146       if (brush->collision == MOD_DPAINT_COL_VOLDIST && brush->flags & MOD_DPAINT_NEGATE_VOLUME) {
4147         volume_factor = 1.0f - volume_factor;
4148         if (inner_proximity) {
4149           proximity_factor = 1.0f - proximity_factor;
4150         }
4151       }
4152 
4153       /* apply final sample depending on final hit type */
4154       if (hit_found == HIT_VOLUME) {
4155         sampleStrength = volume_factor;
4156       }
4157       else if (hit_found == HIT_PROXIMITY) {
4158         /* apply falloff curve to the proximity_factor */
4159         if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP &&
4160             BKE_colorband_evaluate(brush->paint_ramp, (1.0f - proximity_factor), prox_colorband)) {
4161           proximity_factor = prox_colorband[3];
4162         }
4163         else if (brush->proximity_falloff == MOD_DPAINT_PRFALL_CONSTANT) {
4164           proximity_factor = (!inner_proximity || brush->flags & MOD_DPAINT_NEGATE_VOLUME) ? 1.0f :
4165                                                                                              0.0f;
4166         }
4167         /* apply sample */
4168         sampleStrength = proximity_factor;
4169       }
4170 
4171       sampleStrength *= sample_factor;
4172     }
4173     else {
4174       continue;
4175     }
4176 
4177     /* velocity brush, only do on main sample */
4178     if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss == 0 && brushVelocity) {
4179       float weights[3];
4180       float brushPointVelocity[3];
4181       float velocity[3];
4182 
4183       const int v1 = mloop[mlooptri[hitTri].tri[0]].v;
4184       const int v2 = mloop[mlooptri[hitTri].tri[1]].v;
4185       const int v3 = mloop[mlooptri[hitTri].tri[2]].v;
4186 
4187       /* calculate barycentric weights for hit point */
4188       interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, hitCoord);
4189 
4190       /* simple check based on brush surface velocity,
4191        * todo: perhaps implement something that handles volume movement as well. */
4192 
4193       /* interpolate vertex speed vectors to get hit point velocity */
4194       interp_v3_v3v3v3(brushPointVelocity,
4195                        brushVelocity[v1].v,
4196                        brushVelocity[v2].v,
4197                        brushVelocity[v3].v,
4198                        weights);
4199 
4200       /* subtract canvas point velocity */
4201       if (bData->velocity) {
4202         sub_v3_v3v3(velocity, brushPointVelocity, bData->velocity[index].v);
4203       }
4204       else {
4205         copy_v3_v3(velocity, brushPointVelocity);
4206       }
4207       velocity_val = normalize_v3(velocity);
4208 
4209       /* if brush has smudge enabled store brush velocity */
4210       if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE &&
4211           bData->brush_velocity) {
4212         copy_v3_v3(&bData->brush_velocity[index * 4], velocity);
4213         bData->brush_velocity[index * 4 + 3] = velocity_val;
4214       }
4215     }
4216 
4217     /*
4218      * Process hit color and alpha
4219      */
4220     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
4221       float sampleColor[3];
4222       float alpha_factor = 1.0f;
4223 
4224       sampleColor[0] = brush->r;
4225       sampleColor[1] = brush->g;
4226       sampleColor[2] = brush->b;
4227 
4228       /* Sample proximity colorband if required */
4229       if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) {
4230         if (!(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
4231           sampleColor[0] = prox_colorband[0];
4232           sampleColor[1] = prox_colorband[1];
4233           sampleColor[2] = prox_colorband[2];
4234         }
4235       }
4236 
4237       /* Add AA sample */
4238       paintColor[0] += sampleColor[0];
4239       paintColor[1] += sampleColor[1];
4240       paintColor[2] += sampleColor[2];
4241       sampleStrength *= alpha_factor;
4242       numOfHits++;
4243     }
4244 
4245     /* apply sample strength */
4246     brushStrength += sampleStrength;
4247   }  // end supersampling
4248 
4249   /* if any sample was inside paint range */
4250   if (brushStrength > 0.0f || depth > 0.0f) {
4251     /* apply supersampling results */
4252     if (samples > 1) {
4253       brushStrength /= total_sample;
4254     }
4255     CLAMP(brushStrength, 0.0f, 1.0f);
4256 
4257     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
4258       /* Get final pixel color and alpha */
4259       paintColor[0] /= numOfHits;
4260       paintColor[1] /= numOfHits;
4261       paintColor[2] /= numOfHits;
4262     }
4263     /* get final object space depth */
4264     else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
4265       depth /= bData->bNormal[index].normal_scale * total_sample;
4266     }
4267 
4268     dynamicPaint_updatePointData(
4269         surface, index, brush, paintColor, brushStrength, depth, velocity_val, timescale);
4270   }
4271 }
4272 
dynamicPaint_paintMesh(Depsgraph * depsgraph,DynamicPaintSurface * surface,DynamicPaintBrushSettings * brush,Object * brushOb,Scene * scene,float timescale)4273 static bool dynamicPaint_paintMesh(Depsgraph *depsgraph,
4274                                    DynamicPaintSurface *surface,
4275                                    DynamicPaintBrushSettings *brush,
4276                                    Object *brushOb,
4277                                    Scene *scene,
4278                                    float timescale)
4279 {
4280   PaintSurfaceData *sData = surface->data;
4281   PaintBakeData *bData = sData->bData;
4282   Mesh *mesh = NULL;
4283   Vec3f *brushVelocity = NULL;
4284   MVert *mvert = NULL;
4285   const MLoopTri *mlooptri = NULL;
4286   const MLoop *mloop = NULL;
4287 
4288   if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
4289     dynamicPaint_brushMeshCalculateVelocity(
4290         depsgraph, scene, brushOb, brush, &brushVelocity, timescale);
4291   }
4292 
4293   Mesh *brush_mesh = dynamicPaint_brush_mesh_get(brush);
4294   if (brush_mesh == NULL) {
4295     return false;
4296   }
4297 
4298   {
4299     BVHTreeFromMesh treeData = {NULL};
4300     float avg_brushNor[3] = {0.0f};
4301     const float brush_radius = brush->paint_distance * surface->radius_scale;
4302     int numOfVerts;
4303     int ii;
4304     Bounds3D mesh_bb = {{0}};
4305     VolumeGrid *grid = bData->grid;
4306 
4307     mesh = BKE_mesh_copy_for_eval(brush_mesh, false);
4308     mvert = mesh->mvert;
4309     mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
4310     mloop = mesh->mloop;
4311     numOfVerts = mesh->totvert;
4312 
4313     /* Transform collider vertices to global space
4314      * (Faster than transforming per surface point
4315      * coordinates and normals to object space) */
4316     for (ii = 0; ii < numOfVerts; ii++) {
4317       mul_m4_v3(brushOb->obmat, mvert[ii].co);
4318       boundInsert(&mesh_bb, mvert[ii].co);
4319 
4320       /* for proximity project calculate average normal */
4321       if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
4322         float nor[3];
4323         normal_short_to_float_v3(nor, mvert[ii].no);
4324         mul_mat3_m4_v3(brushOb->obmat, nor);
4325         normalize_v3(nor);
4326 
4327         add_v3_v3(avg_brushNor, nor);
4328       }
4329     }
4330 
4331     if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
4332       mul_v3_fl(avg_brushNor, 1.0f / (float)numOfVerts);
4333       /* instead of null vector use positive z */
4334       if (UNLIKELY(normalize_v3(avg_brushNor) == 0.0f)) {
4335         avg_brushNor[2] = 1.0f;
4336       }
4337     }
4338 
4339     /* check bounding box collision */
4340     if (grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius)) {
4341       /* Build a bvh tree from transformed vertices */
4342       if (BKE_bvhtree_from_mesh_get(&treeData, mesh, BVHTREE_FROM_LOOPTRI, 4)) {
4343         int c_index;
4344         int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
4345 
4346         /* loop through space partitioning grid */
4347         for (c_index = 0; c_index < total_cells; c_index++) {
4348           /* check grid cell bounding box */
4349           if (!grid->s_num[c_index] ||
4350               !meshBrush_boundsIntersect(&grid->bounds[c_index], &mesh_bb, brush, brush_radius)) {
4351             continue;
4352           }
4353 
4354           /* loop through cell points and process brush */
4355           DynamicPaintPaintData data = {
4356               .surface = surface,
4357               .brush = brush,
4358               .brushOb = brushOb,
4359               .scene = scene,
4360               .timescale = timescale,
4361               .c_index = c_index,
4362               .mesh = mesh,
4363               .mvert = mvert,
4364               .mloop = mloop,
4365               .mlooptri = mlooptri,
4366               .brush_radius = brush_radius,
4367               .avg_brushNor = avg_brushNor,
4368               .brushVelocity = brushVelocity,
4369               .treeData = &treeData,
4370           };
4371           TaskParallelSettings settings;
4372           BLI_parallel_range_settings_defaults(&settings);
4373           settings.use_threading = (grid->s_num[c_index] > 250);
4374           BLI_task_parallel_range(0,
4375                                   grid->s_num[c_index],
4376                                   &data,
4377                                   dynamic_paint_paint_mesh_cell_point_cb_ex,
4378                                   &settings);
4379         }
4380       }
4381     }
4382     /* free bvh tree */
4383     free_bvhtree_from_mesh(&treeData);
4384     BKE_id_free(NULL, mesh);
4385   }
4386 
4387   /* free brush velocity data */
4388   if (brushVelocity) {
4389     MEM_freeN(brushVelocity);
4390   }
4391 
4392   return true;
4393 }
4394 
4395 /*
4396  * Paint a particle system to the surface
4397  */
dynamic_paint_paint_particle_cell_point_cb_ex(void * __restrict userdata,const int id,const TaskParallelTLS * __restrict UNUSED (tls))4398 static void dynamic_paint_paint_particle_cell_point_cb_ex(
4399     void *__restrict userdata, const int id, const TaskParallelTLS *__restrict UNUSED(tls))
4400 {
4401   const DynamicPaintPaintData *data = userdata;
4402 
4403   const DynamicPaintSurface *surface = data->surface;
4404   const PaintSurfaceData *sData = surface->data;
4405   const PaintBakeData *bData = sData->bData;
4406   VolumeGrid *grid = bData->grid;
4407 
4408   const DynamicPaintBrushSettings *brush = data->brush;
4409 
4410   const ParticleSystem *psys = data->psys;
4411 
4412   const float timescale = data->timescale;
4413   const int c_index = data->c_index;
4414 
4415   KDTree_3d *tree = data->treeData;
4416 
4417   const float solidradius = data->solidradius;
4418   const float smooth = brush->particle_smooth * surface->radius_scale;
4419   const float range = solidradius + smooth;
4420   const float particle_timestep = 0.04f * psys->part->timetweak;
4421 
4422   const int index = grid->t_index[grid->s_pos[c_index] + id];
4423   float disp_intersect = 0.0f;
4424   float radius = 0.0f;
4425   float strength = 0.0f;
4426   int part_index = -1;
4427 
4428   /*
4429    * With predefined radius, there is no variation between particles.
4430    * It's enough to just find the nearest one.
4431    */
4432   {
4433     KDTreeNearest_3d nearest;
4434     float smooth_range, part_solidradius;
4435 
4436     /* Find nearest particle and get distance to it */
4437     BLI_kdtree_3d_find_nearest(tree, bData->realCoord[bData->s_pos[index]].v, &nearest);
4438     /* if outside maximum range, no other particle can influence either */
4439     if (nearest.dist > range) {
4440       return;
4441     }
4442 
4443     if (brush->flags & MOD_DPAINT_PART_RAD) {
4444       /* use particles individual size */
4445       ParticleData *pa = psys->particles + nearest.index;
4446       part_solidradius = pa->size;
4447     }
4448     else {
4449       part_solidradius = solidradius;
4450     }
4451     radius = part_solidradius + smooth;
4452     if (nearest.dist < radius) {
4453       /* distances inside solid radius has maximum influence -> dist = 0 */
4454       smooth_range = max_ff(0.0f, (nearest.dist - part_solidradius));
4455       /* do smoothness if enabled */
4456       if (smooth) {
4457         smooth_range /= smooth;
4458       }
4459 
4460       strength = 1.0f - smooth_range;
4461       disp_intersect = radius - nearest.dist;
4462       part_index = nearest.index;
4463     }
4464   }
4465   /* If using random per particle radius and closest particle didn't give max influence */
4466   if (brush->flags & MOD_DPAINT_PART_RAD && strength < 1.0f && psys->part->randsize > 0.0f) {
4467     /*
4468      * If we use per particle radius, we have to sample all particles
4469      * within max radius range
4470      */
4471     KDTreeNearest_3d *nearest;
4472 
4473     float smooth_range = smooth * (1.0f - strength), dist;
4474     /* calculate max range that can have particles with higher influence than the nearest one */
4475     const float max_range = smooth - strength * smooth + solidradius;
4476     /* Make gcc happy! */
4477     dist = max_range;
4478 
4479     const int particles = BLI_kdtree_3d_range_search(
4480         tree, bData->realCoord[bData->s_pos[index]].v, &nearest, max_range);
4481 
4482     /* Find particle that produces highest influence */
4483     for (int n = 0; n < particles; n++) {
4484       ParticleData *pa = &psys->particles[nearest[n].index];
4485 
4486       /* skip if out of range */
4487       if (nearest[n].dist > (pa->size + smooth)) {
4488         continue;
4489       }
4490 
4491       /* update hit data */
4492       const float s_range = nearest[n].dist - pa->size;
4493       /* skip if higher influence is already found */
4494       if (smooth_range < s_range) {
4495         continue;
4496       }
4497 
4498       /* update hit data */
4499       smooth_range = s_range;
4500       dist = nearest[n].dist;
4501       part_index = nearest[n].index;
4502 
4503       /* If inside solid range and no disp depth required, no need to seek further */
4504       if ((s_range < 0.0f) &&
4505           !ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
4506         break;
4507       }
4508     }
4509 
4510     if (nearest) {
4511       MEM_freeN(nearest);
4512     }
4513 
4514     /* now calculate influence for this particle */
4515     const float rad = radius + smooth;
4516     if ((rad - dist) > disp_intersect) {
4517       disp_intersect = radius - dist;
4518       radius = rad;
4519     }
4520 
4521     /* do smoothness if enabled */
4522     CLAMP_MIN(smooth_range, 0.0f);
4523     if (smooth) {
4524       smooth_range /= smooth;
4525     }
4526 
4527     const float str = 1.0f - smooth_range;
4528     /* if influence is greater, use this one */
4529     if (str > strength) {
4530       strength = str;
4531     }
4532   }
4533 
4534   if (strength > 0.001f) {
4535     float paintColor[4] = {0.0f};
4536     float depth = 0.0f;
4537     float velocity_val = 0.0f;
4538 
4539     /* apply velocity */
4540     if ((brush->flags & MOD_DPAINT_USES_VELOCITY) && (part_index != -1)) {
4541       float velocity[3];
4542       ParticleData *pa = psys->particles + part_index;
4543       mul_v3_v3fl(velocity, pa->state.vel, particle_timestep);
4544 
4545       /* subtract canvas point velocity */
4546       if (bData->velocity) {
4547         sub_v3_v3(velocity, bData->velocity[index].v);
4548       }
4549       velocity_val = normalize_v3(velocity);
4550 
4551       /* store brush velocity for smudge */
4552       if ((surface->type == MOD_DPAINT_SURFACE_T_PAINT) &&
4553           (brush->flags & MOD_DPAINT_DO_SMUDGE && bData->brush_velocity)) {
4554         copy_v3_v3(&bData->brush_velocity[index * 4], velocity);
4555         bData->brush_velocity[index * 4 + 3] = velocity_val;
4556       }
4557     }
4558 
4559     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
4560       copy_v3_v3(paintColor, &brush->r);
4561     }
4562     else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
4563       /* get displace depth */
4564       disp_intersect = (1.0f - sqrtf(disp_intersect / radius)) * radius;
4565       depth = max_ff(0.0f, (radius - disp_intersect) / bData->bNormal[index].normal_scale);
4566     }
4567 
4568     dynamicPaint_updatePointData(
4569         surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
4570   }
4571 }
4572 
dynamicPaint_paintParticles(DynamicPaintSurface * surface,ParticleSystem * psys,DynamicPaintBrushSettings * brush,float timescale)4573 static bool dynamicPaint_paintParticles(DynamicPaintSurface *surface,
4574                                         ParticleSystem *psys,
4575                                         DynamicPaintBrushSettings *brush,
4576                                         float timescale)
4577 {
4578   ParticleSettings *part = psys->part;
4579   PaintSurfaceData *sData = surface->data;
4580   PaintBakeData *bData = sData->bData;
4581   VolumeGrid *grid = bData->grid;
4582 
4583   KDTree_3d *tree;
4584   int particlesAdded = 0;
4585   int invalidParticles = 0;
4586   int p = 0;
4587 
4588   const float solidradius = surface->radius_scale * ((brush->flags & MOD_DPAINT_PART_RAD) ?
4589                                                          part->size :
4590                                                          brush->particle_radius);
4591   const float smooth = brush->particle_smooth * surface->radius_scale;
4592 
4593   const float range = solidradius + smooth;
4594 
4595   Bounds3D part_bb = {{0}};
4596 
4597   if (psys->totpart < 1) {
4598     return true;
4599   }
4600 
4601   /*
4602    * Build a kd-tree to optimize distance search
4603    */
4604   tree = BLI_kdtree_3d_new(psys->totpart);
4605 
4606   /* loop through particles and insert valid ones to the tree */
4607   p = 0;
4608   for (ParticleData *pa = psys->particles; p < psys->totpart; p++, pa++) {
4609     /* Proceed only if particle is active */
4610     if ((pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN) == 0) ||
4611         (pa->alive == PARS_DEAD && (part->flag & PART_DIED) == 0) || (pa->flag & PARS_UNEXIST)) {
4612       continue;
4613     }
4614 
4615     /* for debug purposes check if any NAN particle proceeds
4616      * For some reason they get past activity check, this should rule most of them out */
4617     if (isnan(pa->state.co[0]) || isnan(pa->state.co[1]) || isnan(pa->state.co[2])) {
4618       invalidParticles++;
4619       continue;
4620     }
4621 
4622     /* make sure particle is close enough to canvas */
4623     if (!boundIntersectPoint(&grid->grid_bounds, pa->state.co, range)) {
4624       continue;
4625     }
4626 
4627     BLI_kdtree_3d_insert(tree, p, pa->state.co);
4628 
4629     /* calc particle system bounds */
4630     boundInsert(&part_bb, pa->state.co);
4631 
4632     particlesAdded++;
4633   }
4634   if (invalidParticles) {
4635     CLOG_WARN(&LOG, "Invalid particle(s) found!");
4636   }
4637 
4638   /* If no suitable particles were found, exit */
4639   if (particlesAdded < 1) {
4640     BLI_kdtree_3d_free(tree);
4641     return true;
4642   }
4643 
4644   /* only continue if particle bb is close enough to canvas bb */
4645   if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) {
4646     int c_index;
4647     int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2];
4648 
4649     /* balance tree */
4650     BLI_kdtree_3d_balance(tree);
4651 
4652     /* loop through space partitioning grid */
4653     for (c_index = 0; c_index < total_cells; c_index++) {
4654       /* check cell bounding box */
4655       if (!grid->s_num[c_index] || !boundsIntersectDist(&grid->bounds[c_index], &part_bb, range)) {
4656         continue;
4657       }
4658 
4659       /* loop through cell points */
4660       DynamicPaintPaintData data = {
4661           .surface = surface,
4662           .brush = brush,
4663           .psys = psys,
4664           .solidradius = solidradius,
4665           .timescale = timescale,
4666           .c_index = c_index,
4667           .treeData = tree,
4668       };
4669       TaskParallelSettings settings;
4670       BLI_parallel_range_settings_defaults(&settings);
4671       settings.use_threading = (grid->s_num[c_index] > 250);
4672       BLI_task_parallel_range(0,
4673                               grid->s_num[c_index],
4674                               &data,
4675                               dynamic_paint_paint_particle_cell_point_cb_ex,
4676                               &settings);
4677     }
4678   }
4679   BLI_kdtree_3d_free(tree);
4680 
4681   return true;
4682 }
4683 
4684 /* paint a single point of defined proximity radius to the surface */
dynamic_paint_paint_single_point_cb_ex(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))4685 static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata,
4686                                                    const int index,
4687                                                    const TaskParallelTLS *__restrict UNUSED(tls))
4688 {
4689   const DynamicPaintPaintData *data = userdata;
4690 
4691   const DynamicPaintSurface *surface = data->surface;
4692   const PaintSurfaceData *sData = surface->data;
4693   const PaintBakeData *bData = sData->bData;
4694 
4695   const DynamicPaintBrushSettings *brush = data->brush;
4696 
4697   const float timescale = data->timescale;
4698 
4699   const float brush_radius = data->brush_radius;
4700   const Vec3f *brushVelocity = data->brushVelocity;
4701 
4702   float *pointCoord = data->pointCoord;
4703 
4704   const float distance = len_v3v3(pointCoord, bData->realCoord[bData->s_pos[index]].v);
4705   float colorband[4] = {0.0f};
4706   float strength;
4707 
4708   if (distance > brush_radius) {
4709     return;
4710   }
4711 
4712   /* Smooth range or color ramp */
4713   if (brush->proximity_falloff == MOD_DPAINT_PRFALL_SMOOTH ||
4714       brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP) {
4715     strength = 1.0f - distance / brush_radius;
4716     CLAMP(strength, 0.0f, 1.0f);
4717   }
4718   else {
4719     strength = 1.0f;
4720   }
4721 
4722   if (strength >= 0.001f) {
4723     float paintColor[3] = {0.0f};
4724     float depth = 0.0f;
4725     float velocity_val = 0.0f;
4726 
4727     /* color ramp */
4728     if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP &&
4729         BKE_colorband_evaluate(brush->paint_ramp, (1.0f - strength), colorband)) {
4730       strength = colorband[3];
4731     }
4732 
4733     if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
4734       float velocity[3];
4735 
4736       /* subtract canvas point velocity */
4737       if (bData->velocity) {
4738         sub_v3_v3v3(velocity, brushVelocity->v, bData->velocity[index].v);
4739       }
4740       else {
4741         copy_v3_v3(velocity, brushVelocity->v);
4742       }
4743       velocity_val = len_v3(velocity);
4744 
4745       /* store brush velocity for smudge */
4746       if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE &&
4747           bData->brush_velocity) {
4748         mul_v3_v3fl(&bData->brush_velocity[index * 4], velocity, 1.0f / velocity_val);
4749         bData->brush_velocity[index * 4 + 3] = velocity_val;
4750       }
4751     }
4752 
4753     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
4754       if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP &&
4755           !(brush->flags & MOD_DPAINT_RAMP_ALPHA)) {
4756         paintColor[0] = colorband[0];
4757         paintColor[1] = colorband[1];
4758         paintColor[2] = colorband[2];
4759       }
4760       else {
4761         paintColor[0] = brush->r;
4762         paintColor[1] = brush->g;
4763         paintColor[2] = brush->b;
4764       }
4765     }
4766     else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
4767       /* get displace depth */
4768       const float disp_intersect = (1.0f - sqrtf((brush_radius - distance) / brush_radius)) *
4769                                    brush_radius;
4770       depth = max_ff(0.0f, (brush_radius - disp_intersect) / bData->bNormal[index].normal_scale);
4771     }
4772     dynamicPaint_updatePointData(
4773         surface, index, brush, paintColor, strength, depth, velocity_val, timescale);
4774   }
4775 }
4776 
dynamicPaint_paintSinglePoint(Depsgraph * depsgraph,DynamicPaintSurface * surface,float * pointCoord,DynamicPaintBrushSettings * brush,Object * brushOb,Scene * scene,float timescale)4777 static bool dynamicPaint_paintSinglePoint(
4778     Depsgraph *depsgraph,
4779     DynamicPaintSurface *surface,
4780     /* Cannot be const, because it is assigned to non-const variable.
4781      * NOLINTNEXTLINE: readability-non-const-parameter. */
4782     float *pointCoord,
4783     DynamicPaintBrushSettings *brush,
4784     Object *brushOb,
4785     Scene *scene,
4786     float timescale)
4787 {
4788   PaintSurfaceData *sData = surface->data;
4789   float brush_radius = brush->paint_distance * surface->radius_scale;
4790   Vec3f brushVel;
4791 
4792   if (brush->flags & MOD_DPAINT_USES_VELOCITY) {
4793     dynamicPaint_brushObjectCalculateVelocity(depsgraph, scene, brushOb, &brushVel, timescale);
4794   }
4795 
4796   const Mesh *brush_mesh = dynamicPaint_brush_mesh_get(brush);
4797   const MVert *mvert = brush_mesh->mvert;
4798 
4799   /*
4800    * Loop through every surface point
4801    */
4802   DynamicPaintPaintData data = {
4803       .surface = surface,
4804       .brush = brush,
4805       .brushOb = brushOb,
4806       .scene = scene,
4807       .timescale = timescale,
4808       .mvert = mvert,
4809       .brush_radius = brush_radius,
4810       .brushVelocity = &brushVel,
4811       .pointCoord = pointCoord,
4812   };
4813   TaskParallelSettings settings;
4814   BLI_parallel_range_settings_defaults(&settings);
4815   settings.use_threading = (sData->total_points > 1000);
4816   BLI_task_parallel_range(
4817       0, sData->total_points, &data, dynamic_paint_paint_single_point_cb_ex, &settings);
4818 
4819   return true;
4820 }
4821 
4822 /***************************** Dynamic Paint Step / Baking ******************************/
4823 
4824 /*
4825  * Calculate current frame distances and directions for adjacency data
4826  */
4827 
dynamic_paint_prepare_adjacency_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))4828 static void dynamic_paint_prepare_adjacency_cb(void *__restrict userdata,
4829                                                const int index,
4830                                                const TaskParallelTLS *__restrict UNUSED(tls))
4831 {
4832   PaintSurfaceData *sData = userdata;
4833   PaintBakeData *bData = sData->bData;
4834   BakeAdjPoint *bNeighs = bData->bNeighs;
4835   PaintAdjData *adj_data = sData->adj_data;
4836   Vec3f *realCoord = bData->realCoord;
4837 
4838   const int num_neighs = adj_data->n_num[index];
4839 
4840   for (int i = 0; i < num_neighs; i++) {
4841     const int n_index = adj_data->n_index[index] + i;
4842     const int t_index = adj_data->n_target[n_index];
4843 
4844     /* dir vec */
4845     sub_v3_v3v3(bNeighs[n_index].dir,
4846                 realCoord[bData->s_pos[t_index]].v,
4847                 realCoord[bData->s_pos[index]].v);
4848     /* dist */
4849     bNeighs[n_index].dist = normalize_v3(bNeighs[n_index].dir);
4850   }
4851 }
4852 
dynamicPaint_prepareAdjacencyData(DynamicPaintSurface * surface,const bool force_init)4853 static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, const bool force_init)
4854 {
4855   PaintSurfaceData *sData = surface->data;
4856   PaintBakeData *bData = sData->bData;
4857   BakeAdjPoint *bNeighs;
4858   PaintAdjData *adj_data = sData->adj_data;
4859 
4860   int index;
4861 
4862   if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) {
4863     return;
4864   }
4865 
4866   if (bData->bNeighs) {
4867     MEM_freeN(bData->bNeighs);
4868   }
4869   bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets * sizeof(*bNeighs),
4870                                          "PaintEffectBake");
4871   if (!bNeighs) {
4872     return;
4873   }
4874 
4875   TaskParallelSettings settings;
4876   BLI_parallel_range_settings_defaults(&settings);
4877   settings.use_threading = (sData->total_points > 1000);
4878   BLI_task_parallel_range(
4879       0, sData->total_points, sData, dynamic_paint_prepare_adjacency_cb, &settings);
4880 
4881   /* calculate average values (single thread).
4882    * Note: tried to put this in threaded callback (using _reduce feature),
4883    * but gave ~30% slower result! */
4884   bData->average_dist = 0.0;
4885   for (index = 0; index < sData->total_points; index++) {
4886     int numOfNeighs = adj_data->n_num[index];
4887 
4888     for (int i = 0; i < numOfNeighs; i++) {
4889       bData->average_dist += (double)bNeighs[adj_data->n_index[index] + i].dist;
4890     }
4891   }
4892   bData->average_dist /= adj_data->total_targets;
4893 }
4894 
4895 /* Find two adjacency points (closest_id) and influence (closest_d)
4896  * to move paint towards when affected by a force. */
surface_determineForceTargetPoints(const PaintSurfaceData * sData,const int index,const float force[3],float closest_d[2],int closest_id[2])4897 static void surface_determineForceTargetPoints(const PaintSurfaceData *sData,
4898                                                const int index,
4899                                                const float force[3],
4900                                                float closest_d[2],
4901                                                int closest_id[2])
4902 {
4903   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
4904   const int numOfNeighs = sData->adj_data->n_num[index];
4905 
4906   closest_id[0] = closest_id[1] = -1;
4907   closest_d[0] = closest_d[1] = -1.0f;
4908 
4909   /* find closest neigh */
4910   for (int i = 0; i < numOfNeighs; i++) {
4911     const int n_index = sData->adj_data->n_index[index] + i;
4912     const float dir_dot = dot_v3v3(bNeighs[n_index].dir, force);
4913 
4914     if (dir_dot > closest_d[0] && dir_dot > 0.0f) {
4915       closest_d[0] = dir_dot;
4916       closest_id[0] = n_index;
4917     }
4918   }
4919 
4920   if (closest_d[0] < 0.0f) {
4921     return;
4922   }
4923 
4924   /* find second closest neigh */
4925   for (int i = 0; i < numOfNeighs; i++) {
4926     const int n_index = sData->adj_data->n_index[index] + i;
4927 
4928     if (n_index == closest_id[0]) {
4929       continue;
4930     }
4931 
4932     const float dir_dot = dot_v3v3(bNeighs[n_index].dir, force);
4933     const float closest_dot = dot_v3v3(bNeighs[n_index].dir, bNeighs[closest_id[0]].dir);
4934 
4935     /* only accept neighbor at "other side" of the first one in relation to force dir
4936      * so make sure angle between this and closest neigh is greater than first angle. */
4937     if (dir_dot > closest_d[1] && closest_dot < closest_d[0] && dir_dot > 0.0f) {
4938       closest_d[1] = dir_dot;
4939       closest_id[1] = n_index;
4940     }
4941   }
4942 
4943   /* if two valid neighs found, calculate how force effect is divided evenly between them
4944    * (so that d[0] + d[1] = 1.0) */
4945   if (closest_id[1] != -1) {
4946     float force_proj[3];
4947     float tangent[3];
4948     const float neigh_diff = acosf(
4949         dot_v3v3(bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir));
4950     float force_intersect;
4951     float temp;
4952 
4953     /* project force vector on the plane determined by these two neighbor points
4954      * and calculate relative force angle from it. */
4955     cross_v3_v3v3(tangent, bNeighs[closest_id[0]].dir, bNeighs[closest_id[1]].dir);
4956     normalize_v3(tangent);
4957     force_intersect = dot_v3v3(force, tangent);
4958     madd_v3_v3v3fl(force_proj, force, tangent, (-1.0f) * force_intersect);
4959     normalize_v3(force_proj);
4960 
4961     /* get drip factor based on force dir in relation to angle between those neighbors */
4962     temp = dot_v3v3(bNeighs[closest_id[0]].dir, force_proj);
4963     CLAMP(temp, -1.0f, 1.0f); /* float precision might cause values > 1.0f that return infinite */
4964     closest_d[1] = acosf(temp) / neigh_diff;
4965     closest_d[0] = 1.0f - closest_d[1];
4966 
4967     /* and multiply depending on how deeply force intersects surface */
4968     temp = fabsf(force_intersect);
4969     CLAMP(temp, 0.0f, 1.0f);
4970     mul_v2_fl(closest_d, acosf(temp) / (float)M_PI_2);
4971   }
4972   else {
4973     /* if only single neighbor, still linearize force intersection effect */
4974     closest_d[0] = 1.0f - acosf(closest_d[0]) / (float)M_PI_2;
4975   }
4976 }
4977 
dynamicPaint_doSmudge(DynamicPaintSurface * surface,DynamicPaintBrushSettings * brush,float timescale)4978 static void dynamicPaint_doSmudge(DynamicPaintSurface *surface,
4979                                   DynamicPaintBrushSettings *brush,
4980                                   float timescale)
4981 {
4982   PaintSurfaceData *sData = surface->data;
4983   PaintBakeData *bData = sData->bData;
4984   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
4985   float max_velocity = 0.0f;
4986 
4987   if (!sData->adj_data) {
4988     return;
4989   }
4990 
4991   /* find max velocity */
4992   for (int index = 0; index < sData->total_points; index++) {
4993     float vel = bData->brush_velocity[index * 4 + 3];
4994     CLAMP_MIN(max_velocity, vel);
4995   }
4996 
4997   int steps = (int)ceil((double)max_velocity / bData->average_dist * (double)timescale);
4998   CLAMP(steps, 0, 12);
4999   float eff_scale = brush->smudge_strength / (float)steps * timescale;
5000 
5001   for (int step = 0; step < steps; step++) {
5002     for (int index = 0; index < sData->total_points; index++) {
5003 
5004       if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL) {
5005         continue;
5006       }
5007 
5008       PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
5009       float smudge_str = bData->brush_velocity[index * 4 + 3];
5010 
5011       /* force targets */
5012       int closest_id[2];
5013       float closest_d[2];
5014 
5015       if (!smudge_str) {
5016         continue;
5017       }
5018 
5019       /* get force affect points */
5020       surface_determineForceTargetPoints(
5021           sData, index, &bData->brush_velocity[index * 4], closest_d, closest_id);
5022 
5023       /* Apply movement towards those two points */
5024       for (int i = 0; i < 2; i++) {
5025         int n_index = closest_id[i];
5026         if (n_index != -1 && closest_d[i] > 0.0f) {
5027           float dir_dot = closest_d[i], dir_factor;
5028           float speed_scale = eff_scale * smudge_str / bNeighs[n_index].dist;
5029           PaintPoint *ePoint = &(
5030               (PaintPoint *)sData->type_data)[sData->adj_data->n_target[n_index]];
5031 
5032           /* just skip if angle is too extreme */
5033           if (dir_dot <= 0.0f) {
5034             continue;
5035           }
5036 
5037           dir_factor = dir_dot * speed_scale;
5038           CLAMP_MAX(dir_factor, brush->smudge_strength);
5039 
5040           /* mix new color and alpha */
5041           mixColors(ePoint->color, ePoint->color[3], pPoint->color, pPoint->color[3], dir_factor);
5042           ePoint->color[3] = ePoint->color[3] * (1.0f - dir_factor) +
5043                              pPoint->color[3] * dir_factor;
5044 
5045           /* smudge "wet layer" */
5046           mixColors(ePoint->e_color,
5047                     ePoint->e_color[3],
5048                     pPoint->e_color,
5049                     pPoint->e_color[3],
5050                     dir_factor);
5051           ePoint->e_color[3] = ePoint->e_color[3] * (1.0f - dir_factor) +
5052                                pPoint->e_color[3] * dir_factor;
5053           pPoint->wetness *= (1.0f - dir_factor);
5054         }
5055       }
5056     }
5057   }
5058 }
5059 
5060 typedef struct DynamicPaintEffectData {
5061   const DynamicPaintSurface *surface;
5062   Scene *scene;
5063 
5064   float *force;
5065   ListBase *effectors;
5066   const void *prevPoint;
5067   const float eff_scale;
5068 
5069   uint8_t *point_locks;
5070 
5071   const float wave_speed;
5072   const float wave_scale;
5073   const float wave_max_slope;
5074 
5075   const float dt;
5076   const float min_dist;
5077   const float damp_factor;
5078   const bool reset_wave;
5079 } DynamicPaintEffectData;
5080 
5081 /*
5082  * Prepare data required by effects for current frame.
5083  * Returns number of steps required
5084  */
dynamic_paint_prepare_effect_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5085 static void dynamic_paint_prepare_effect_cb(void *__restrict userdata,
5086                                             const int index,
5087                                             const TaskParallelTLS *__restrict UNUSED(tls))
5088 {
5089   const DynamicPaintEffectData *data = userdata;
5090 
5091   const DynamicPaintSurface *surface = data->surface;
5092   const PaintSurfaceData *sData = surface->data;
5093   const PaintBakeData *bData = sData->bData;
5094   Vec3f *realCoord = bData->realCoord;
5095 
5096   Scene *scene = data->scene;
5097 
5098   float *force = data->force;
5099   ListBase *effectors = data->effectors;
5100 
5101   float forc[3] = {0};
5102   float vel[3] = {0};
5103 
5104   /* apply force fields */
5105   if (effectors) {
5106     EffectedPoint epoint;
5107     pd_point_from_loc(scene, realCoord[bData->s_pos[index]].v, vel, index, &epoint);
5108     epoint.vel_to_sec = 1.0f;
5109     BKE_effectors_apply(effectors, NULL, surface->effector_weights, &epoint, forc, NULL, NULL);
5110   }
5111 
5112   /* if global gravity is enabled, add it too */
5113   if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
5114     /* also divide by 10 to about match default grav
5115      * with default force strength (1.0). */
5116     madd_v3_v3fl(forc,
5117                  scene->physics_settings.gravity,
5118                  surface->effector_weights->global_gravity * surface->effector_weights->weight[0] /
5119                      10.f);
5120   }
5121 
5122   /* add surface point velocity and acceleration if enabled */
5123   if (bData->velocity) {
5124     if (surface->drip_vel) {
5125       madd_v3_v3fl(forc, bData->velocity[index].v, surface->drip_vel * (-1.0f));
5126     }
5127 
5128     /* acceleration */
5129     if (bData->prev_velocity && surface->drip_acc) {
5130       float acc[3];
5131       copy_v3_v3(acc, bData->velocity[index].v);
5132       sub_v3_v3(acc, bData->prev_velocity[index].v);
5133       madd_v3_v3fl(forc, acc, surface->drip_acc * (-1.0f));
5134     }
5135   }
5136 
5137   /* force strength, and normalize force vec */
5138   force[index * 4 + 3] = normalize_v3_v3(&force[index * 4], forc);
5139 }
5140 
dynamicPaint_prepareEffectStep(struct Depsgraph * depsgraph,DynamicPaintSurface * surface,Scene * scene,Object * ob,float ** force,float timescale)5141 static int dynamicPaint_prepareEffectStep(struct Depsgraph *depsgraph,
5142                                           DynamicPaintSurface *surface,
5143                                           Scene *scene,
5144                                           Object *ob,
5145                                           float **force,
5146                                           float timescale)
5147 {
5148   double average_force = 0.0f;
5149   float shrink_speed = 0.0f, spread_speed = 0.0f;
5150   float fastest_effect, avg_dist;
5151   int steps;
5152   PaintSurfaceData *sData = surface->data;
5153   PaintBakeData *bData = sData->bData;
5154 
5155   /* Init force data if required */
5156   if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
5157     ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, surface->effector_weights);
5158 
5159     /* allocate memory for force data (dir vector + strength) */
5160     *force = MEM_mallocN(sizeof(float[4]) * sData->total_points, "PaintEffectForces");
5161 
5162     if (*force) {
5163       DynamicPaintEffectData data = {
5164           .surface = surface,
5165           .scene = scene,
5166           .force = *force,
5167           .effectors = effectors,
5168       };
5169       TaskParallelSettings settings;
5170       BLI_parallel_range_settings_defaults(&settings);
5171       settings.use_threading = (sData->total_points > 1000);
5172       BLI_task_parallel_range(
5173           0, sData->total_points, &data, dynamic_paint_prepare_effect_cb, &settings);
5174 
5175       /* calculate average values (single thread) */
5176       for (int index = 0; index < sData->total_points; index++) {
5177         average_force += (double)(*force)[index * 4 + 3];
5178       }
5179       average_force /= sData->total_points;
5180     }
5181     BKE_effectors_free(effectors);
5182   }
5183 
5184   /* Get number of required steps using average point distance
5185    * so that just a few ultra close pixels wont up substeps to max. */
5186 
5187   /* adjust number of required substep by fastest active effect */
5188   if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD) {
5189     spread_speed = surface->spread_speed;
5190   }
5191   if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK) {
5192     shrink_speed = surface->shrink_speed;
5193   }
5194 
5195   fastest_effect = max_fff(spread_speed, shrink_speed, average_force);
5196   avg_dist = bData->average_dist * (double)CANVAS_REL_SIZE / (double)getSurfaceDimension(sData);
5197 
5198   steps = (int)ceilf(1.5f * EFF_MOVEMENT_PER_FRAME * fastest_effect / avg_dist * timescale);
5199   CLAMP(steps, 1, 20);
5200 
5201   return steps;
5202 }
5203 
5204 /**
5205  * Processes active effect step.
5206  */
dynamic_paint_effect_spread_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5207 static void dynamic_paint_effect_spread_cb(void *__restrict userdata,
5208                                            const int index,
5209                                            const TaskParallelTLS *__restrict UNUSED(tls))
5210 {
5211   const DynamicPaintEffectData *data = userdata;
5212 
5213   const DynamicPaintSurface *surface = data->surface;
5214   const PaintSurfaceData *sData = surface->data;
5215 
5216   if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL) {
5217     return;
5218   }
5219 
5220   const int numOfNeighs = sData->adj_data->n_num[index];
5221   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
5222   PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
5223   const PaintPoint *prevPoint = data->prevPoint;
5224   const float eff_scale = data->eff_scale;
5225 
5226   const int *n_index = sData->adj_data->n_index;
5227   const int *n_target = sData->adj_data->n_target;
5228 
5229   /* Loop through neighboring points */
5230   for (int i = 0; i < numOfNeighs; i++) {
5231     const int n_idx = n_index[index] + i;
5232     float w_factor;
5233     const PaintPoint *pPoint_prev = &prevPoint[n_target[n_idx]];
5234     const float speed_scale = (bNeighs[n_idx].dist < eff_scale) ? 1.0f :
5235                                                                   eff_scale / bNeighs[n_idx].dist;
5236     const float color_mix = min_fff(pPoint_prev->wetness, pPoint->wetness, 1.0f) * 0.25f *
5237                             surface->color_spread_speed;
5238 
5239     /* do color mixing */
5240     if (color_mix) {
5241       mixColors(pPoint->e_color,
5242                 pPoint->e_color[3],
5243                 pPoint_prev->e_color,
5244                 pPoint_prev->e_color[3],
5245                 color_mix);
5246     }
5247 
5248     /* Only continue if surrounding point has higher wetness */
5249     if (pPoint_prev->wetness < pPoint->wetness || pPoint_prev->wetness < MIN_WETNESS) {
5250       continue;
5251     }
5252 
5253     w_factor = 1.0f / numOfNeighs * min_ff(pPoint_prev->wetness, 1.0f) * speed_scale;
5254     CLAMP(w_factor, 0.0f, 1.0f);
5255 
5256     /* mix new wetness and color */
5257     pPoint->wetness = pPoint->wetness + w_factor * (pPoint_prev->wetness - pPoint->wetness);
5258     pPoint->e_color[3] = mixColors(pPoint->e_color,
5259                                    pPoint->e_color[3],
5260                                    pPoint_prev->e_color,
5261                                    pPoint_prev->e_color[3],
5262                                    w_factor);
5263   }
5264 }
5265 
dynamic_paint_effect_shrink_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5266 static void dynamic_paint_effect_shrink_cb(void *__restrict userdata,
5267                                            const int index,
5268                                            const TaskParallelTLS *__restrict UNUSED(tls))
5269 {
5270   const DynamicPaintEffectData *data = userdata;
5271 
5272   const DynamicPaintSurface *surface = data->surface;
5273   const PaintSurfaceData *sData = surface->data;
5274 
5275   if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL) {
5276     return;
5277   }
5278 
5279   const int numOfNeighs = sData->adj_data->n_num[index];
5280   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
5281   PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
5282   const PaintPoint *prevPoint = data->prevPoint;
5283   const float eff_scale = data->eff_scale;
5284   float totalAlpha = 0.0f;
5285 
5286   const int *n_index = sData->adj_data->n_index;
5287   const int *n_target = sData->adj_data->n_target;
5288 
5289   /* Loop through neighboring points */
5290   for (int i = 0; i < numOfNeighs; i++) {
5291     const int n_idx = n_index[index] + i;
5292     const float speed_scale = (bNeighs[n_idx].dist < eff_scale) ? 1.0f :
5293                                                                   eff_scale / bNeighs[n_idx].dist;
5294     const PaintPoint *pPoint_prev = &prevPoint[n_target[n_idx]];
5295     float a_factor, ea_factor, w_factor;
5296 
5297     totalAlpha += pPoint_prev->e_color[3];
5298 
5299     /* Check if neighboring point has lower alpha,
5300      * if so, decrease this point's alpha as well. */
5301     if (pPoint->color[3] <= 0.0f && pPoint->e_color[3] <= 0.0f && pPoint->wetness <= 0.0f) {
5302       continue;
5303     }
5304 
5305     /* decrease factor for dry paint alpha */
5306     a_factor = max_ff((1.0f - pPoint_prev->color[3]) / numOfNeighs *
5307                           (pPoint->color[3] - pPoint_prev->color[3]) * speed_scale,
5308                       0.0f);
5309     /* decrease factor for wet paint alpha */
5310     ea_factor = max_ff((1.0f - pPoint_prev->e_color[3]) / 8 *
5311                            (pPoint->e_color[3] - pPoint_prev->e_color[3]) * speed_scale,
5312                        0.0f);
5313     /* decrease factor for paint wetness */
5314     w_factor = max_ff((1.0f - pPoint_prev->wetness) / 8 *
5315                           (pPoint->wetness - pPoint_prev->wetness) * speed_scale,
5316                       0.0f);
5317 
5318     pPoint->color[3] -= a_factor;
5319     CLAMP_MIN(pPoint->color[3], 0.0f);
5320     pPoint->e_color[3] -= ea_factor;
5321     CLAMP_MIN(pPoint->e_color[3], 0.0f);
5322     pPoint->wetness -= w_factor;
5323     CLAMP_MIN(pPoint->wetness, 0.0f);
5324   }
5325 }
5326 
dynamic_paint_effect_drip_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5327 static void dynamic_paint_effect_drip_cb(void *__restrict userdata,
5328                                          const int index,
5329                                          const TaskParallelTLS *__restrict UNUSED(tls))
5330 {
5331   const DynamicPaintEffectData *data = userdata;
5332 
5333   const DynamicPaintSurface *surface = data->surface;
5334   const PaintSurfaceData *sData = surface->data;
5335 
5336   if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL) {
5337     return;
5338   }
5339 
5340   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
5341   PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
5342   const PaintPoint *prevPoint = data->prevPoint;
5343   const PaintPoint *pPoint_prev = &prevPoint[index];
5344   const float *force = data->force;
5345   const float eff_scale = data->eff_scale;
5346 
5347   const int *n_target = sData->adj_data->n_target;
5348 
5349   uint8_t *point_locks = data->point_locks;
5350 
5351   int closest_id[2];
5352   float closest_d[2];
5353 
5354   /* adjust drip speed depending on wetness */
5355   float w_factor = pPoint_prev->wetness - 0.025f;
5356   if (w_factor <= 0) {
5357     return;
5358   }
5359   CLAMP(w_factor, 0.0f, 1.0f);
5360 
5361   float ppoint_wetness_diff = 0.0f;
5362 
5363   /* get force affect points */
5364   surface_determineForceTargetPoints(sData, index, &force[index * 4], closest_d, closest_id);
5365 
5366   /* Apply movement towards those two points */
5367   for (int i = 0; i < 2; i++) {
5368     const int n_idx = closest_id[i];
5369     if (n_idx != -1 && closest_d[i] > 0.0f) {
5370       const float dir_dot = closest_d[i];
5371 
5372       /* just skip if angle is too extreme */
5373       if (dir_dot <= 0.0f) {
5374         continue;
5375       }
5376 
5377       float dir_factor, a_factor;
5378       const float speed_scale = eff_scale * force[index * 4 + 3] / bNeighs[n_idx].dist;
5379 
5380       const unsigned int n_trgt = (unsigned int)n_target[n_idx];
5381 
5382       /* Sort of spinlock, but only for given ePoint.
5383        * Since the odds a same ePoint is modified at the same time by several threads is very low,
5384        * this is much more efficient than a global spin lock. */
5385       const unsigned int epointlock_idx = n_trgt / 8;
5386       const uint8_t epointlock_bitmask = 1 << (n_trgt & 7); /* 7 == 0b111 */
5387       while (atomic_fetch_and_or_uint8(&point_locks[epointlock_idx], epointlock_bitmask) &
5388              epointlock_bitmask) {
5389         /* pass */
5390       }
5391 
5392       PaintPoint *ePoint = &((PaintPoint *)sData->type_data)[n_trgt];
5393       const float e_wet = ePoint->wetness;
5394 
5395       dir_factor = min_ff(0.5f, dir_dot * min_ff(speed_scale, 1.0f) * w_factor);
5396 
5397       /* mix new wetness */
5398       ePoint->wetness += dir_factor;
5399       CLAMP(ePoint->wetness, 0.0f, MAX_WETNESS);
5400 
5401       /* mix new color */
5402       a_factor = dir_factor / pPoint_prev->wetness;
5403       CLAMP(a_factor, 0.0f, 1.0f);
5404       mixColors(ePoint->e_color,
5405                 ePoint->e_color[3],
5406                 pPoint_prev->e_color,
5407                 pPoint_prev->e_color[3],
5408                 a_factor);
5409       /* dripping is supposed to preserve alpha level */
5410       if (pPoint_prev->e_color[3] > ePoint->e_color[3]) {
5411         ePoint->e_color[3] += a_factor * pPoint_prev->e_color[3];
5412         CLAMP_MAX(ePoint->e_color[3], pPoint_prev->e_color[3]);
5413       }
5414 
5415       /* Decrease paint wetness on current point (just store diff here,
5416        * that way we can only lock current point once at the end to apply it). */
5417       ppoint_wetness_diff += (ePoint->wetness - e_wet);
5418 
5419 #ifndef NDEBUG
5420       {
5421         uint8_t ret = atomic_fetch_and_and_uint8(&point_locks[epointlock_idx],
5422                                                  ~epointlock_bitmask);
5423         BLI_assert(ret & epointlock_bitmask);
5424       }
5425 #else
5426       atomic_fetch_and_and_uint8(&point_locks[epointlock_idx], ~epointlock_bitmask);
5427 #endif
5428     }
5429   }
5430 
5431   {
5432     const unsigned int ppointlock_idx = index / 8;
5433     const uint8_t ppointlock_bitmask = 1 << (index & 7); /* 7 == 0b111 */
5434     while (atomic_fetch_and_or_uint8(&point_locks[ppointlock_idx], ppointlock_bitmask) &
5435            ppointlock_bitmask) {
5436       /* pass */
5437     }
5438 
5439     pPoint->wetness -= ppoint_wetness_diff;
5440     CLAMP(pPoint->wetness, 0.0f, MAX_WETNESS);
5441 
5442 #ifndef NDEBUG
5443     {
5444       uint8_t ret = atomic_fetch_and_and_uint8(&point_locks[ppointlock_idx], ~ppointlock_bitmask);
5445       BLI_assert(ret & ppointlock_bitmask);
5446     }
5447 #else
5448     atomic_fetch_and_and_uint8(&point_locks[ppointlock_idx], ~ppointlock_bitmask);
5449 #endif
5450   }
5451 }
5452 
dynamicPaint_doEffectStep(DynamicPaintSurface * surface,float * force,PaintPoint * prevPoint,float timescale,float steps)5453 static void dynamicPaint_doEffectStep(
5454     DynamicPaintSurface *surface,
5455     /* Cannot be const, because it is assigned to non-const variable.
5456      * NOLINTNEXTLINE: readability-non-const-parameter. */
5457     float *force,
5458     PaintPoint *prevPoint,
5459     float timescale,
5460     float steps)
5461 {
5462   PaintSurfaceData *sData = surface->data;
5463 
5464   const float distance_scale = getSurfaceDimension(sData) / CANVAS_REL_SIZE;
5465   timescale /= steps;
5466 
5467   if (!sData->adj_data) {
5468     return;
5469   }
5470 
5471   /*
5472    * Spread Effect
5473    */
5474   if (surface->effect & MOD_DPAINT_EFFECT_DO_SPREAD) {
5475     const float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * surface->spread_speed *
5476                             timescale;
5477 
5478     /* Copy current surface to the previous points array to read unmodified values */
5479     memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(struct PaintPoint));
5480 
5481     DynamicPaintEffectData data = {
5482         .surface = surface,
5483         .prevPoint = prevPoint,
5484         .eff_scale = eff_scale,
5485     };
5486     TaskParallelSettings settings;
5487     BLI_parallel_range_settings_defaults(&settings);
5488     settings.use_threading = (sData->total_points > 1000);
5489     BLI_task_parallel_range(
5490         0, sData->total_points, &data, dynamic_paint_effect_spread_cb, &settings);
5491   }
5492 
5493   /*
5494    * Shrink Effect
5495    */
5496   if (surface->effect & MOD_DPAINT_EFFECT_DO_SHRINK) {
5497     const float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * surface->shrink_speed *
5498                             timescale;
5499 
5500     /* Copy current surface to the previous points array to read unmodified values */
5501     memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(struct PaintPoint));
5502 
5503     DynamicPaintEffectData data = {
5504         .surface = surface,
5505         .prevPoint = prevPoint,
5506         .eff_scale = eff_scale,
5507     };
5508     TaskParallelSettings settings;
5509     BLI_parallel_range_settings_defaults(&settings);
5510     settings.use_threading = (sData->total_points > 1000);
5511     BLI_task_parallel_range(
5512         0, sData->total_points, &data, dynamic_paint_effect_shrink_cb, &settings);
5513   }
5514 
5515   /*
5516    * Drip Effect
5517    */
5518   if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP && force) {
5519     const float eff_scale = distance_scale * EFF_MOVEMENT_PER_FRAME * timescale / 2.0f;
5520 
5521     /* Same as BLI_bitmask, but handled atomicaly as 'ePoint' locks. */
5522     const size_t point_locks_size = (sData->total_points / 8) + 1;
5523     uint8_t *point_locks = MEM_callocN(sizeof(*point_locks) * point_locks_size, __func__);
5524 
5525     /* Copy current surface to the previous points array to read unmodified values */
5526     memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(struct PaintPoint));
5527 
5528     DynamicPaintEffectData data = {
5529         .surface = surface,
5530         .prevPoint = prevPoint,
5531         .eff_scale = eff_scale,
5532         .force = force,
5533         .point_locks = point_locks,
5534     };
5535     TaskParallelSettings settings;
5536     BLI_parallel_range_settings_defaults(&settings);
5537     settings.use_threading = (sData->total_points > 1000);
5538     BLI_task_parallel_range(
5539         0, sData->total_points, &data, dynamic_paint_effect_drip_cb, &settings);
5540 
5541     MEM_freeN(point_locks);
5542   }
5543 }
5544 
dynamic_paint_border_cb(void * __restrict userdata,const int b_index,const TaskParallelTLS * __restrict UNUSED (tls))5545 static void dynamic_paint_border_cb(void *__restrict userdata,
5546                                     const int b_index,
5547                                     const TaskParallelTLS *__restrict UNUSED(tls))
5548 {
5549   const DynamicPaintEffectData *data = userdata;
5550 
5551   const DynamicPaintSurface *surface = data->surface;
5552   const PaintSurfaceData *sData = surface->data;
5553 
5554   const int index = sData->adj_data->border[b_index];
5555 
5556   const int numOfNeighs = sData->adj_data->n_num[index];
5557   PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
5558 
5559   const int *n_index = sData->adj_data->n_index;
5560   const int *n_target = sData->adj_data->n_target;
5561 
5562   /* Average neighboring points. Intermediaries use premultiplied alpha. */
5563   float mix_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5564   float mix_e_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5565   float mix_wetness = 0.0f;
5566 
5567   for (int i = 0; i < numOfNeighs; i++) {
5568     const int n_idx = n_index[index] + i;
5569     const int target = n_target[n_idx];
5570 
5571     PaintPoint *pPoint2 = &((PaintPoint *)sData->type_data)[target];
5572 
5573     BLI_assert(!(sData->adj_data->flags[target] & ADJ_BORDER_PIXEL));
5574 
5575     madd_v3_v3fl(mix_color, pPoint2->color, pPoint2->color[3]);
5576     mix_color[3] += pPoint2->color[3];
5577 
5578     madd_v3_v3fl(mix_e_color, pPoint2->e_color, pPoint2->e_color[3]);
5579     mix_e_color[3] += pPoint2->e_color[3];
5580 
5581     mix_wetness += pPoint2->wetness;
5582   }
5583 
5584   const float divisor = 1.0f / numOfNeighs;
5585 
5586   if (mix_color[3]) {
5587     pPoint->color[3] = mix_color[3] * divisor;
5588     mul_v3_v3fl(pPoint->color, mix_color, divisor / pPoint->color[3]);
5589   }
5590   else {
5591     pPoint->color[3] = 0.0f;
5592   }
5593 
5594   if (mix_e_color[3]) {
5595     pPoint->e_color[3] = mix_e_color[3] * divisor;
5596     mul_v3_v3fl(pPoint->e_color, mix_e_color, divisor / pPoint->e_color[3]);
5597   }
5598   else {
5599     pPoint->e_color[3] = 0.0f;
5600   }
5601 
5602   pPoint->wetness = mix_wetness / numOfNeighs;
5603 }
5604 
dynamicPaint_doBorderStep(DynamicPaintSurface * surface)5605 static void dynamicPaint_doBorderStep(DynamicPaintSurface *surface)
5606 {
5607   PaintSurfaceData *sData = surface->data;
5608 
5609   if (!sData->adj_data || !sData->adj_data->border) {
5610     return;
5611   }
5612 
5613   /* Don't use prevPoint, relying on the condition that neighbors are never border pixels. */
5614   DynamicPaintEffectData data = {
5615       .surface = surface,
5616   };
5617 
5618   TaskParallelSettings settings;
5619   BLI_parallel_range_settings_defaults(&settings);
5620   settings.use_threading = (sData->adj_data->total_border > 1000);
5621   BLI_task_parallel_range(
5622       0, sData->adj_data->total_border, &data, dynamic_paint_border_cb, &settings);
5623 }
5624 
dynamic_paint_wave_step_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5625 static void dynamic_paint_wave_step_cb(void *__restrict userdata,
5626                                        const int index,
5627                                        const TaskParallelTLS *__restrict UNUSED(tls))
5628 {
5629   const DynamicPaintEffectData *data = userdata;
5630 
5631   const DynamicPaintSurface *surface = data->surface;
5632   const PaintSurfaceData *sData = surface->data;
5633   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
5634   const PaintWavePoint *prevPoint = data->prevPoint;
5635 
5636   const float wave_speed = data->wave_speed;
5637   const float wave_scale = data->wave_scale;
5638   const float wave_max_slope = data->wave_max_slope;
5639 
5640   const float dt = data->dt;
5641   const float min_dist = data->min_dist;
5642   const float damp_factor = data->damp_factor;
5643 
5644   PaintWavePoint *wPoint = &((PaintWavePoint *)sData->type_data)[index];
5645   const int numOfNeighs = sData->adj_data->n_num[index];
5646   float force = 0.0f, avg_dist = 0.0f, avg_height = 0.0f, avg_n_height = 0.0f;
5647   int numOfN = 0, numOfRN = 0;
5648 
5649   if (wPoint->state > 0) {
5650     return;
5651   }
5652 
5653   const int *n_index = sData->adj_data->n_index;
5654   const int *n_target = sData->adj_data->n_target;
5655   const int *adj_flags = sData->adj_data->flags;
5656 
5657   /* calculate force from surrounding points */
5658   for (int i = 0; i < numOfNeighs; i++) {
5659     const int n_idx = n_index[index] + i;
5660     float dist = bNeighs[n_idx].dist * wave_scale;
5661     const PaintWavePoint *tPoint = &prevPoint[n_target[n_idx]];
5662 
5663     if (!dist || tPoint->state > 0) {
5664       continue;
5665     }
5666 
5667     CLAMP_MIN(dist, min_dist);
5668     avg_dist += dist;
5669     numOfN++;
5670 
5671     /* count average height for edge points for open borders */
5672     if (!(adj_flags[n_target[n_idx]] & ADJ_ON_MESH_EDGE)) {
5673       avg_n_height += tPoint->height;
5674       numOfRN++;
5675     }
5676 
5677     force += (tPoint->height - wPoint->height) / (dist * dist);
5678     avg_height += tPoint->height;
5679   }
5680   avg_dist = (numOfN) ? avg_dist / numOfN : 0.0f;
5681 
5682   if (surface->flags & MOD_DPAINT_WAVE_OPEN_BORDERS && adj_flags[index] & ADJ_ON_MESH_EDGE) {
5683     /* if open borders, apply a fake height to keep waves going on */
5684     avg_n_height = (numOfRN) ? avg_n_height / numOfRN : 0.0f;
5685     wPoint->height = (dt * wave_speed * avg_n_height + wPoint->height * avg_dist) /
5686                      (avg_dist + dt * wave_speed);
5687   }
5688   /* else do wave eq */
5689   else {
5690     /* add force towards zero height based on average dist */
5691     if (avg_dist) {
5692       force += (0.0f - wPoint->height) * surface->wave_spring / (avg_dist * avg_dist) / 2.0f;
5693     }
5694 
5695     /* change point velocity */
5696     wPoint->velocity += force * dt * wave_speed * wave_speed;
5697     /* damping */
5698     wPoint->velocity *= damp_factor;
5699     /* and new height */
5700     wPoint->height += wPoint->velocity * dt;
5701 
5702     /* limit wave slope steepness */
5703     if (wave_max_slope && avg_dist) {
5704       const float max_offset = wave_max_slope * avg_dist;
5705       const float offset = (numOfN) ? (avg_height / numOfN - wPoint->height) : 0.0f;
5706       if (offset > max_offset) {
5707         wPoint->height += offset - max_offset;
5708       }
5709       else if (offset < -max_offset) {
5710         wPoint->height += offset + max_offset;
5711       }
5712     }
5713   }
5714 
5715   if (data->reset_wave) {
5716     /* if there wasn't any brush intersection, clear isect height */
5717     if (wPoint->state == DPAINT_WAVE_NONE) {
5718       wPoint->brush_isect = 0.0f;
5719     }
5720     wPoint->state = DPAINT_WAVE_NONE;
5721   }
5722 }
5723 
dynamicPaint_doWaveStep(DynamicPaintSurface * surface,float timescale)5724 static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
5725 {
5726   PaintSurfaceData *sData = surface->data;
5727   BakeAdjPoint *bNeighs = sData->bData->bNeighs;
5728   int index;
5729   int steps, ss;
5730   float dt, min_dist, damp_factor;
5731   const float wave_speed = surface->wave_speed;
5732   const float wave_max_slope = (surface->wave_smoothness >= 0.01f) ?
5733                                    (0.5f / surface->wave_smoothness) :
5734                                    0.0f;
5735   double average_dist = 0.0f;
5736   const float canvas_size = getSurfaceDimension(sData);
5737   const float wave_scale = CANVAS_REL_SIZE / canvas_size;
5738 
5739   /* allocate memory */
5740   PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points * sizeof(PaintWavePoint), __func__);
5741   if (!prevPoint) {
5742     return;
5743   }
5744 
5745   /* calculate average neigh distance (single thread) */
5746   for (index = 0; index < sData->total_points; index++) {
5747     int numOfNeighs = sData->adj_data->n_num[index];
5748 
5749     for (int i = 0; i < numOfNeighs; i++) {
5750       average_dist += (double)bNeighs[sData->adj_data->n_index[index] + i].dist;
5751     }
5752   }
5753   average_dist *= (double)wave_scale / sData->adj_data->total_targets;
5754 
5755   /* determine number of required steps */
5756   steps = (int)ceil((double)(WAVE_TIME_FAC * timescale * surface->wave_timescale) /
5757                     (average_dist / (double)wave_speed / 3));
5758   CLAMP(steps, 1, 20);
5759   timescale /= steps;
5760 
5761   /* apply simulation values for final timescale */
5762   dt = WAVE_TIME_FAC * timescale * surface->wave_timescale;
5763   min_dist = wave_speed * dt * 1.5f;
5764   damp_factor = pow((1.0f - surface->wave_damping), timescale * surface->wave_timescale);
5765 
5766   for (ss = 0; ss < steps; ss++) {
5767     /* copy previous frame data */
5768     memcpy(prevPoint, sData->type_data, sData->total_points * sizeof(PaintWavePoint));
5769 
5770     DynamicPaintEffectData data = {
5771         .surface = surface,
5772         .prevPoint = prevPoint,
5773         .wave_speed = wave_speed,
5774         .wave_scale = wave_scale,
5775         .wave_max_slope = wave_max_slope,
5776         .dt = dt,
5777         .min_dist = min_dist,
5778         .damp_factor = damp_factor,
5779         .reset_wave = (ss == steps - 1),
5780     };
5781     TaskParallelSettings settings;
5782     BLI_parallel_range_settings_defaults(&settings);
5783     settings.use_threading = (sData->total_points > 1000);
5784     BLI_task_parallel_range(0, sData->total_points, &data, dynamic_paint_wave_step_cb, &settings);
5785   }
5786 
5787   MEM_freeN(prevPoint);
5788 }
5789 
5790 /* Do dissolve and fading effects */
dynamic_paint_surface_needs_dry_dissolve(DynamicPaintSurface * surface)5791 static bool dynamic_paint_surface_needs_dry_dissolve(DynamicPaintSurface *surface)
5792 {
5793   return (((surface->type == MOD_DPAINT_SURFACE_T_PAINT) &&
5794            (surface->flags & (MOD_DPAINT_USE_DRYING | MOD_DPAINT_DISSOLVE))) ||
5795           (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WEIGHT) &&
5796            (surface->flags & MOD_DPAINT_DISSOLVE)));
5797 }
5798 
5799 typedef struct DynamicPaintDissolveDryData {
5800   const DynamicPaintSurface *surface;
5801   const float timescale;
5802 } DynamicPaintDissolveDryData;
5803 
dynamic_paint_surface_pre_step_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5804 static void dynamic_paint_surface_pre_step_cb(void *__restrict userdata,
5805                                               const int index,
5806                                               const TaskParallelTLS *__restrict UNUSED(tls))
5807 {
5808   const DynamicPaintDissolveDryData *data = userdata;
5809 
5810   const DynamicPaintSurface *surface = data->surface;
5811   const PaintSurfaceData *sData = surface->data;
5812   const float timescale = data->timescale;
5813 
5814   /* Do drying dissolve effects */
5815   if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
5816     PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
5817     /* drying */
5818     if (surface->flags & MOD_DPAINT_USE_DRYING) {
5819       if (pPoint->wetness >= MIN_WETNESS) {
5820         float f_color[4];
5821         float p_wetness = pPoint->wetness;
5822 
5823         value_dissolve(&pPoint->wetness,
5824                        surface->dry_speed,
5825                        timescale,
5826                        (surface->flags & MOD_DPAINT_DRY_LOG) != 0);
5827         CLAMP_MIN(pPoint->wetness, 0.0f);
5828 
5829         if (pPoint->wetness < surface->color_dry_threshold) {
5830           float dry_ratio = pPoint->wetness / p_wetness;
5831 
5832           /*
5833            * Slowly "shift" paint from wet layer to dry layer as it drys:
5834            */
5835           /* make sure alpha values are within proper range */
5836           CLAMP(pPoint->color[3], 0.0f, 1.0f);
5837           CLAMP(pPoint->e_color[3], 0.0f, 1.0f);
5838 
5839           /* get current final blended color of these layers */
5840           blendColors(
5841               pPoint->color, pPoint->color[3], pPoint->e_color, pPoint->e_color[3], f_color);
5842           /* reduce wet layer alpha by dry factor */
5843           pPoint->e_color[3] *= dry_ratio;
5844 
5845           /* Now calculate new alpha for dry layer that keeps final blended color unchanged. */
5846           pPoint->color[3] = (f_color[3] - pPoint->e_color[3]) / (1.0f - pPoint->e_color[3]);
5847           /* For each rgb component, calculate a new dry layer color that keeps the final blend
5848            * color with these new alpha values. (wet layer color doesn't change). */
5849           if (pPoint->color[3]) {
5850             for (int i = 0; i < 3; i++) {
5851               pPoint->color[i] = (f_color[i] * f_color[3] -
5852                                   pPoint->e_color[i] * pPoint->e_color[3]) /
5853                                  (pPoint->color[3] * (1.0f - pPoint->e_color[3]));
5854             }
5855           }
5856         }
5857 
5858         pPoint->state = DPAINT_PAINT_WET;
5859       }
5860       /* in case of just dryed paint, just mix it to the dry layer and mark it empty */
5861       else if (pPoint->state > 0) {
5862         float f_color[4];
5863         blendColors(pPoint->color, pPoint->color[3], pPoint->e_color, pPoint->e_color[3], f_color);
5864         copy_v4_v4(pPoint->color, f_color);
5865         /* clear wet layer */
5866         pPoint->wetness = 0.0f;
5867         pPoint->e_color[3] = 0.0f;
5868         pPoint->state = DPAINT_PAINT_DRY;
5869       }
5870     }
5871 
5872     if (surface->flags & MOD_DPAINT_DISSOLVE) {
5873       value_dissolve(&pPoint->color[3],
5874                      surface->diss_speed,
5875                      timescale,
5876                      (surface->flags & MOD_DPAINT_DISSOLVE_LOG) != 0);
5877       CLAMP_MIN(pPoint->color[3], 0.0f);
5878 
5879       value_dissolve(&pPoint->e_color[3],
5880                      surface->diss_speed,
5881                      timescale,
5882                      (surface->flags & MOD_DPAINT_DISSOLVE_LOG) != 0);
5883       CLAMP_MIN(pPoint->e_color[3], 0.0f);
5884     }
5885   }
5886   /* dissolve for float types */
5887   else if (surface->flags & MOD_DPAINT_DISSOLVE &&
5888            (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE ||
5889             surface->type == MOD_DPAINT_SURFACE_T_WEIGHT)) {
5890     float *point = &((float *)sData->type_data)[index];
5891     /* log or linear */
5892     value_dissolve(
5893         point, surface->diss_speed, timescale, (surface->flags & MOD_DPAINT_DISSOLVE_LOG) != 0);
5894     CLAMP_MIN(*point, 0.0f);
5895   }
5896 }
5897 
dynamicPaint_surfaceHasMoved(DynamicPaintSurface * surface,Object * ob)5898 static bool dynamicPaint_surfaceHasMoved(DynamicPaintSurface *surface, Object *ob)
5899 {
5900   PaintSurfaceData *sData = surface->data;
5901   PaintBakeData *bData = sData->bData;
5902   Mesh *mesh = dynamicPaint_canvas_mesh_get(surface->canvas);
5903   MVert *mvert = mesh->mvert;
5904 
5905   int numOfVerts = mesh->totvert;
5906 
5907   if (!bData->prev_verts) {
5908     return true;
5909   }
5910 
5911   /* matrix comparison */
5912   if (!equals_m4m4(bData->prev_obmat, ob->obmat)) {
5913     return true;
5914   }
5915 
5916   /* vertices */
5917   for (int i = 0; i < numOfVerts; i++) {
5918     if (!equals_v3v3(bData->prev_verts[i].co, mvert[i].co)) {
5919       return true;
5920     }
5921   }
5922 
5923   return false;
5924 }
5925 
5926 /* Prepare for surface step by creating PaintBakeNormal data */
5927 typedef struct DynamicPaintGenerateBakeData {
5928   const DynamicPaintSurface *surface;
5929   Object *ob;
5930 
5931   const MVert *mvert;
5932   const Vec3f *canvas_verts;
5933 
5934   const bool do_velocity_data;
5935   const bool new_bdata;
5936 } DynamicPaintGenerateBakeData;
5937 
dynamic_paint_generate_bake_data_cb(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))5938 static void dynamic_paint_generate_bake_data_cb(void *__restrict userdata,
5939                                                 const int index,
5940                                                 const TaskParallelTLS *__restrict UNUSED(tls))
5941 {
5942   const DynamicPaintGenerateBakeData *data = userdata;
5943 
5944   const DynamicPaintSurface *surface = data->surface;
5945   const PaintSurfaceData *sData = surface->data;
5946   const PaintAdjData *adj_data = sData->adj_data;
5947   const PaintBakeData *bData = sData->bData;
5948 
5949   Object *ob = data->ob;
5950 
5951   const MVert *mvert = data->mvert;
5952   const Vec3f *canvas_verts = data->canvas_verts;
5953 
5954   const bool do_velocity_data = data->do_velocity_data;
5955   const bool new_bdata = data->new_bdata;
5956 
5957   float prev_point[3] = {0.0f, 0.0f, 0.0f};
5958   float temp_nor[3];
5959 
5960   if (do_velocity_data && !new_bdata) {
5961     copy_v3_v3(prev_point, bData->realCoord[bData->s_pos[index]].v);
5962   }
5963 
5964   /*
5965    * Calculate current 3D-position and normal of each surface point
5966    */
5967   if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) {
5968     float n1[3], n2[3], n3[3];
5969     const ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
5970     const PaintUVPoint *tPoint = &((PaintUVPoint *)f_data->uv_p)[index];
5971 
5972     bData->s_num[index] = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
5973     bData->s_pos[index] = index * bData->s_num[index];
5974 
5975     /* per sample coordinates */
5976     for (int ss = 0; ss < bData->s_num[index]; ss++) {
5977       interp_v3_v3v3v3(bData->realCoord[bData->s_pos[index] + ss].v,
5978                        canvas_verts[tPoint->v1].v,
5979                        canvas_verts[tPoint->v2].v,
5980                        canvas_verts[tPoint->v3].v,
5981                        f_data->barycentricWeights[index * bData->s_num[index] + ss].v);
5982     }
5983 
5984     /* Calculate current pixel surface normal */
5985     normal_short_to_float_v3(n1, mvert[tPoint->v1].no);
5986     normal_short_to_float_v3(n2, mvert[tPoint->v2].no);
5987     normal_short_to_float_v3(n3, mvert[tPoint->v3].no);
5988 
5989     interp_v3_v3v3v3(
5990         temp_nor, n1, n2, n3, f_data->barycentricWeights[index * bData->s_num[index]].v);
5991     normalize_v3(temp_nor);
5992     if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
5993       /* Prepare surface normal directional scale to easily convert
5994        * brush intersection amount between global and local space */
5995       float scaled_nor[3];
5996       mul_v3_v3v3(scaled_nor, temp_nor, ob->scale);
5997       bData->bNormal[index].normal_scale = len_v3(scaled_nor);
5998     }
5999     mul_mat3_m4_v3(ob->obmat, temp_nor);
6000     normalize_v3(temp_nor);
6001     negate_v3_v3(bData->bNormal[index].invNorm, temp_nor);
6002   }
6003   else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
6004     int ss;
6005     if (surface->flags & MOD_DPAINT_ANTIALIAS && adj_data) {
6006       bData->s_num[index] = adj_data->n_num[index] + 1;
6007       bData->s_pos[index] = adj_data->n_index[index] + index;
6008     }
6009     else {
6010       bData->s_num[index] = 1;
6011       bData->s_pos[index] = index;
6012     }
6013 
6014     /* calculate position for each sample */
6015     for (ss = 0; ss < bData->s_num[index]; ss++) {
6016       /* first sample is always point center */
6017       copy_v3_v3(bData->realCoord[bData->s_pos[index] + ss].v, canvas_verts[index].v);
6018       if (ss > 0) {
6019         int t_index = adj_data->n_index[index] + (ss - 1);
6020         /* get vertex position at 1/3 of each neigh edge */
6021         mul_v3_fl(bData->realCoord[bData->s_pos[index] + ss].v, 2.0f / 3.0f);
6022         madd_v3_v3fl(bData->realCoord[bData->s_pos[index] + ss].v,
6023                      canvas_verts[adj_data->n_target[t_index]].v,
6024                      1.0f / 3.0f);
6025       }
6026     }
6027 
6028     /* normal */
6029     normal_short_to_float_v3(temp_nor, mvert[index].no);
6030     if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) {
6031       /* Prepare surface normal directional scale to easily convert
6032        * brush intersection amount between global and local space */
6033       float scaled_nor[3];
6034       mul_v3_v3v3(scaled_nor, temp_nor, ob->scale);
6035       bData->bNormal[index].normal_scale = len_v3(scaled_nor);
6036     }
6037     mul_mat3_m4_v3(ob->obmat, temp_nor);
6038     normalize_v3(temp_nor);
6039     negate_v3_v3(bData->bNormal[index].invNorm, temp_nor);
6040   }
6041 
6042   /* calculate speed vector */
6043   if (do_velocity_data && !new_bdata && !bData->clear) {
6044     sub_v3_v3v3(bData->velocity[index].v, bData->realCoord[bData->s_pos[index]].v, prev_point);
6045   }
6046 }
6047 
dynamicPaint_generateBakeData(DynamicPaintSurface * surface,Depsgraph * depsgraph,Object * ob)6048 static bool dynamicPaint_generateBakeData(DynamicPaintSurface *surface,
6049                                           Depsgraph *depsgraph,
6050                                           Object *ob)
6051 {
6052   PaintSurfaceData *sData = surface->data;
6053   PaintBakeData *bData = sData->bData;
6054   Mesh *mesh = dynamicPaint_canvas_mesh_get(surface->canvas);
6055   int index;
6056   bool new_bdata = false;
6057   const bool do_velocity_data = ((surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) ||
6058                                  (surface_getBrushFlags(surface, depsgraph) &
6059                                   BRUSH_USES_VELOCITY));
6060   const bool do_accel_data = (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) != 0;
6061 
6062   int canvasNumOfVerts = mesh->totvert;
6063   MVert *mvert = mesh->mvert;
6064   Vec3f *canvas_verts;
6065 
6066   if (bData) {
6067     const bool surface_moved = dynamicPaint_surfaceHasMoved(surface, ob);
6068 
6069     /* get previous speed for accelertaion */
6070     if (do_accel_data && bData->prev_velocity && bData->velocity) {
6071       memcpy(bData->prev_velocity, bData->velocity, sData->total_points * sizeof(Vec3f));
6072     }
6073 
6074     /* reset speed vectors */
6075     if (do_velocity_data && bData->velocity && (bData->clear || !surface_moved)) {
6076       memset(bData->velocity, 0, sData->total_points * sizeof(Vec3f));
6077     }
6078 
6079     /* if previous data exists and mesh hasn't moved, no need to recalc */
6080     if (!surface_moved) {
6081       return true;
6082     }
6083   }
6084 
6085   canvas_verts = (struct Vec3f *)MEM_mallocN(canvasNumOfVerts * sizeof(struct Vec3f),
6086                                              "Dynamic Paint transformed canvas verts");
6087   if (!canvas_verts) {
6088     return false;
6089   }
6090 
6091   /* allocate memory if required */
6092   if (!bData) {
6093     sData->bData = bData = (struct PaintBakeData *)MEM_callocN(sizeof(struct PaintBakeData),
6094                                                                "Dynamic Paint bake data");
6095     if (!bData) {
6096       if (canvas_verts) {
6097         MEM_freeN(canvas_verts);
6098       }
6099       return false;
6100     }
6101 
6102     /* Init bdata */
6103     bData->bNormal = (struct PaintBakeNormal *)MEM_mallocN(
6104         sData->total_points * sizeof(struct PaintBakeNormal), "Dynamic Paint step data");
6105     bData->s_pos = MEM_mallocN(sData->total_points * sizeof(unsigned int),
6106                                "Dynamic Paint bData s_pos");
6107     bData->s_num = MEM_mallocN(sData->total_points * sizeof(unsigned int),
6108                                "Dynamic Paint bData s_num");
6109     bData->realCoord = (struct Vec3f *)MEM_mallocN(surface_totalSamples(surface) * sizeof(Vec3f),
6110                                                    "Dynamic Paint point coords");
6111     bData->prev_verts = MEM_mallocN(canvasNumOfVerts * sizeof(MVert),
6112                                     "Dynamic Paint bData prev_verts");
6113 
6114     /* if any allocation failed, free everything */
6115     if (!bData->bNormal || !bData->s_pos || !bData->s_num || !bData->realCoord || !canvas_verts) {
6116       if (bData->bNormal) {
6117         MEM_freeN(bData->bNormal);
6118       }
6119       if (bData->s_pos) {
6120         MEM_freeN(bData->s_pos);
6121       }
6122       if (bData->s_num) {
6123         MEM_freeN(bData->s_num);
6124       }
6125       if (bData->realCoord) {
6126         MEM_freeN(bData->realCoord);
6127       }
6128       if (canvas_verts) {
6129         MEM_freeN(canvas_verts);
6130       }
6131 
6132       return setError(surface->canvas, N_("Not enough free memory"));
6133     }
6134 
6135     new_bdata = true;
6136   }
6137 
6138   if (do_velocity_data && !bData->velocity) {
6139     bData->velocity = (struct Vec3f *)MEM_callocN(sData->total_points * sizeof(Vec3f),
6140                                                   "Dynamic Paint velocity");
6141   }
6142   if (do_accel_data && !bData->prev_velocity) {
6143     bData->prev_velocity = (struct Vec3f *)MEM_mallocN(sData->total_points * sizeof(Vec3f),
6144                                                        "Dynamic Paint prev velocity");
6145     /* copy previous vel */
6146     if (bData->prev_velocity && bData->velocity) {
6147       memcpy(bData->prev_velocity, bData->velocity, sData->total_points * sizeof(Vec3f));
6148     }
6149   }
6150 
6151   /*
6152    * Make a transformed copy of canvas derived mesh vertices to avoid recalculation.
6153    */
6154   bData->mesh_bounds.valid = false;
6155   for (index = 0; index < canvasNumOfVerts; index++) {
6156     copy_v3_v3(canvas_verts[index].v, mvert[index].co);
6157     mul_m4_v3(ob->obmat, canvas_verts[index].v);
6158     boundInsert(&bData->mesh_bounds, canvas_verts[index].v);
6159   }
6160 
6161   /*
6162    * Prepare each surface point for a new step
6163    */
6164   DynamicPaintGenerateBakeData data = {
6165       .surface = surface,
6166       .ob = ob,
6167       .mvert = mvert,
6168       .canvas_verts = canvas_verts,
6169       .do_velocity_data = do_velocity_data,
6170       .new_bdata = new_bdata,
6171   };
6172   TaskParallelSettings settings;
6173   BLI_parallel_range_settings_defaults(&settings);
6174   settings.use_threading = (sData->total_points > 1000);
6175   BLI_task_parallel_range(
6176       0, sData->total_points, &data, dynamic_paint_generate_bake_data_cb, &settings);
6177 
6178   MEM_freeN(canvas_verts);
6179 
6180   /* generate surface space partitioning grid */
6181   surfaceGenerateGrid(surface);
6182   /* calculate current frame adjacency point distances and global dirs */
6183   dynamicPaint_prepareAdjacencyData(surface, false);
6184 
6185   /* Copy current frame vertices to check against in next frame */
6186   copy_m4_m4(bData->prev_obmat, ob->obmat);
6187   memcpy(bData->prev_verts, mvert, canvasNumOfVerts * sizeof(MVert));
6188 
6189   bData->clear = 0;
6190 
6191   return true;
6192 }
6193 
6194 /*
6195  * Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface.
6196  */
dynamicPaint_doStep(Depsgraph * depsgraph,Scene * scene,Object * ob,DynamicPaintSurface * surface,float timescale,float subframe)6197 static int dynamicPaint_doStep(Depsgraph *depsgraph,
6198                                Scene *scene,
6199                                Object *ob,
6200                                DynamicPaintSurface *surface,
6201                                float timescale,
6202                                float subframe)
6203 {
6204   PaintSurfaceData *sData = surface->data;
6205   PaintBakeData *bData = sData->bData;
6206   DynamicPaintCanvasSettings *canvas = surface->canvas;
6207   const bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
6208   int ret = 1;
6209 
6210   if (sData->total_points < 1) {
6211     return 0;
6212   }
6213 
6214   if (dynamic_paint_surface_needs_dry_dissolve(surface)) {
6215     DynamicPaintDissolveDryData data = {
6216         .surface = surface,
6217         .timescale = timescale,
6218     };
6219     TaskParallelSettings settings;
6220     BLI_parallel_range_settings_defaults(&settings);
6221     settings.use_threading = (sData->total_points > 1000);
6222     BLI_task_parallel_range(
6223         0, sData->total_points, &data, dynamic_paint_surface_pre_step_cb, &settings);
6224   }
6225 
6226   /*
6227    * Loop through surface's target paint objects and do painting
6228    */
6229   {
6230     unsigned int numobjects;
6231     Object **objects = BKE_collision_objects_create(
6232         depsgraph, NULL, surface->brush_group, &numobjects, eModifierType_DynamicPaint);
6233 
6234     /* backup current scene frame */
6235     int scene_frame = scene->r.cfra;
6236     float scene_subframe = scene->r.subframe;
6237 
6238     for (int i = 0; i < numobjects; i++) {
6239       Object *brushObj = objects[i];
6240 
6241       /* check if target has an active dp modifier */
6242       ModifierData *md = BKE_modifiers_findby_type(brushObj, eModifierType_DynamicPaint);
6243       if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) {
6244         DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
6245         /* make sure we're dealing with a brush */
6246         if (pmd2->brush && pmd2->type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
6247           DynamicPaintBrushSettings *brush = pmd2->brush;
6248 
6249           /* calculate brush speed vectors if required */
6250           if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE) {
6251             bData->brush_velocity = MEM_callocN(sizeof(float[4]) * sData->total_points,
6252                                                 "Dynamic Paint brush velocity");
6253             /* init adjacency data if not already */
6254             if (!sData->adj_data) {
6255               dynamicPaint_initAdjacencyData(surface, true);
6256             }
6257             if (!bData->bNeighs) {
6258               dynamicPaint_prepareAdjacencyData(surface, true);
6259             }
6260           }
6261 
6262           /* update object data on this subframe */
6263           if (subframe) {
6264             scene_setSubframe(scene, subframe);
6265             BKE_object_modifier_update_subframe(depsgraph,
6266                                                 scene,
6267                                                 brushObj,
6268                                                 true,
6269                                                 SUBFRAME_RECURSION,
6270                                                 BKE_scene_frame_get(scene),
6271                                                 eModifierType_DynamicPaint);
6272           }
6273 
6274           /* Apply brush on the surface depending on its collision type */
6275           if (brush->psys && brush->psys->part &&
6276               ELEM(brush->psys->part->type,
6277                    PART_EMITTER,
6278                    PART_FLUID,
6279                    PART_FLUID_FLIP,
6280                    PART_FLUID_SPRAY,
6281                    PART_FLUID_BUBBLE,
6282                    PART_FLUID_FOAM,
6283                    PART_FLUID_TRACER,
6284                    PART_FLUID_SPRAYFOAM,
6285                    PART_FLUID_SPRAYBUBBLE,
6286                    PART_FLUID_FOAMBUBBLE,
6287                    PART_FLUID_SPRAYFOAMBUBBLE) &&
6288               psys_check_enabled(brushObj, brush->psys, for_render)) {
6289             /* Paint a particle system */
6290             dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
6291           }
6292           /* Object center distance: */
6293           if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
6294             dynamicPaint_paintSinglePoint(
6295                 depsgraph, surface, brushObj->loc, brush, brushObj, scene, timescale);
6296           }
6297           /* Mesh volume/proximity: */
6298           else if (brushObj != ob) {
6299             dynamicPaint_paintMesh(depsgraph, surface, brush, brushObj, scene, timescale);
6300           }
6301 
6302           /* reset object to its original state */
6303           if (subframe) {
6304             scene->r.cfra = scene_frame;
6305             scene->r.subframe = scene_subframe;
6306             BKE_object_modifier_update_subframe(depsgraph,
6307                                                 scene,
6308                                                 brushObj,
6309                                                 true,
6310                                                 SUBFRAME_RECURSION,
6311                                                 BKE_scene_frame_get(scene),
6312                                                 eModifierType_DynamicPaint);
6313           }
6314 
6315           /* process special brush effects, like smudge */
6316           if (bData->brush_velocity) {
6317             if (surface->type == MOD_DPAINT_SURFACE_T_PAINT &&
6318                 brush->flags & MOD_DPAINT_DO_SMUDGE) {
6319               dynamicPaint_doSmudge(surface, brush, timescale);
6320             }
6321             MEM_freeN(bData->brush_velocity);
6322             bData->brush_velocity = NULL;
6323           }
6324         }
6325       }
6326     }
6327 
6328     BKE_collision_objects_free(objects);
6329   }
6330 
6331   /* surfaces operations that use adjacency data */
6332   if (sData->adj_data && bData->bNeighs) {
6333     /* wave type surface simulation step */
6334     if (surface->type == MOD_DPAINT_SURFACE_T_WAVE) {
6335       dynamicPaint_doWaveStep(surface, timescale);
6336     }
6337 
6338     /* paint surface effects */
6339     if (surface->effect && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
6340       int steps = 1, s;
6341       PaintPoint *prevPoint;
6342       float *force = NULL;
6343 
6344       /* Allocate memory for surface previous points to read unchanged values from */
6345       prevPoint = MEM_mallocN(sData->total_points * sizeof(struct PaintPoint),
6346                               "PaintSurfaceDataCopy");
6347       if (!prevPoint) {
6348         return setError(canvas, N_("Not enough free memory"));
6349       }
6350 
6351       /* Prepare effects and get number of required steps */
6352       steps = dynamicPaint_prepareEffectStep(depsgraph, surface, scene, ob, &force, timescale);
6353       for (s = 0; s < steps; s++) {
6354         dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps);
6355       }
6356 
6357       /* Free temporary effect data */
6358       if (prevPoint) {
6359         MEM_freeN(prevPoint);
6360       }
6361       if (force) {
6362         MEM_freeN(force);
6363       }
6364     }
6365 
6366     /* paint island border pixels */
6367     if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
6368       dynamicPaint_doBorderStep(surface);
6369     }
6370   }
6371 
6372   return ret;
6373 }
6374 
6375 /**
6376  * Calculate a single frame and included sub-frames for surface.
6377  */
dynamicPaint_calculateFrame(DynamicPaintSurface * surface,struct Depsgraph * depsgraph,Scene * scene,Object * cObject,int frame)6378 int dynamicPaint_calculateFrame(DynamicPaintSurface *surface,
6379                                 struct Depsgraph *depsgraph,
6380                                 Scene *scene,
6381                                 Object *cObject,
6382                                 int frame)
6383 {
6384   float timescale = 1.0f;
6385 
6386   /* apply previous displace on derivedmesh if incremental surface */
6387   if (surface->flags & MOD_DPAINT_DISP_INCREMENTAL) {
6388     dynamicPaint_applySurfaceDisplace(surface, dynamicPaint_canvas_mesh_get(surface->canvas));
6389   }
6390 
6391   /* update bake data */
6392   dynamicPaint_generateBakeData(surface, depsgraph, cObject);
6393 
6394   /* don't do substeps for first frame */
6395   if (surface->substeps && (frame != surface->start_frame)) {
6396     int st;
6397     timescale = 1.0f / (surface->substeps + 1);
6398 
6399     for (st = 1; st <= surface->substeps; st++) {
6400       float subframe = ((float)st) / (surface->substeps + 1);
6401       if (!dynamicPaint_doStep(depsgraph, scene, cObject, surface, timescale, subframe)) {
6402         return 0;
6403       }
6404     }
6405   }
6406 
6407   return dynamicPaint_doStep(depsgraph, scene, cObject, surface, timescale, 0.0f);
6408 }
6409