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