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  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14  *
15  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
16  * All rights reserved.
17  *
18  * The Original Code is: some of this file.
19  */
20 
21 /** \file
22  * \ingroup edsculpt
23  * \brief Functions to paint images in 2D and 3D.
24  */
25 
26 #include <float.h>
27 #include <math.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #ifdef WIN32
34 #  include "BLI_winstuff.h"
35 #endif
36 
37 #include "BLI_blenlib.h"
38 #include "BLI_linklist.h"
39 #include "BLI_math.h"
40 #include "BLI_math_bits.h"
41 #include "BLI_math_color_blend.h"
42 #include "BLI_memarena.h"
43 #include "BLI_task.h"
44 #include "BLI_threads.h"
45 #include "BLI_utildefines.h"
46 
47 #include "atomic_ops.h"
48 
49 #include "BLT_translation.h"
50 
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
53 
54 #include "DNA_brush_types.h"
55 #include "DNA_material_types.h"
56 #include "DNA_mesh_types.h"
57 #include "DNA_meshdata_types.h"
58 #include "DNA_node_types.h"
59 #include "DNA_object_types.h"
60 
61 #include "BKE_brush.h"
62 #include "BKE_camera.h"
63 #include "BKE_colorband.h"
64 #include "BKE_colortools.h"
65 #include "BKE_context.h"
66 #include "BKE_customdata.h"
67 #include "BKE_global.h"
68 #include "BKE_idprop.h"
69 #include "BKE_image.h"
70 #include "BKE_lib_id.h"
71 #include "BKE_main.h"
72 #include "BKE_material.h"
73 #include "BKE_mesh.h"
74 #include "BKE_mesh_mapping.h"
75 #include "BKE_mesh_runtime.h"
76 #include "BKE_node.h"
77 #include "BKE_paint.h"
78 #include "BKE_report.h"
79 #include "BKE_scene.h"
80 #include "BKE_screen.h"
81 
82 #include "DEG_depsgraph.h"
83 #include "DEG_depsgraph_query.h"
84 
85 #include "ED_node.h"
86 #include "ED_object.h"
87 #include "ED_paint.h"
88 #include "ED_screen.h"
89 #include "ED_uvedit.h"
90 #include "ED_view3d.h"
91 #include "ED_view3d_offscreen.h"
92 
93 #include "GPU_capabilities.h"
94 #include "GPU_init_exit.h"
95 
96 #include "WM_api.h"
97 #include "WM_types.h"
98 
99 #include "RNA_access.h"
100 #include "RNA_define.h"
101 #include "RNA_enum_types.h"
102 
103 #include "IMB_colormanagement.h"
104 
105 //#include "bmesh_tools.h"
106 
107 #include "paint_intern.h"
108 
109 static void partial_redraw_array_init(ImagePaintPartialRedraw *pr);
110 
111 /* Defines and Structs */
112 /* unit_float_to_uchar_clamp as inline function */
f_to_char(const float val)113 BLI_INLINE uchar f_to_char(const float val)
114 {
115   return unit_float_to_uchar_clamp(val);
116 }
117 
118 /* ProjectionPaint defines */
119 
120 /* approx the number of buckets to have under the brush,
121  * used with the brush size to set the ps->buckets_x and ps->buckets_y value.
122  *
123  * When 3 - a brush should have ~9 buckets under it at once
124  * ...this helps for threading while painting as well as
125  * avoiding initializing pixels that wont touch the brush */
126 #define PROJ_BUCKET_BRUSH_DIV 4
127 
128 #define PROJ_BUCKET_RECT_MIN 4
129 #define PROJ_BUCKET_RECT_MAX 256
130 
131 #define PROJ_BOUNDBOX_DIV 8
132 #define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
133 
134 //#define PROJ_DEBUG_PAINT 1
135 //#define PROJ_DEBUG_NOSEAMBLEED 1
136 //#define PROJ_DEBUG_PRINT_CLIP 1
137 #define PROJ_DEBUG_WINCLIP 1
138 
139 #ifndef PROJ_DEBUG_NOSEAMBLEED
140 /* projectFaceSeamFlags options */
141 //#define PROJ_FACE_IGNORE  (1<<0)  /* When the face is hidden, backfacing or occluded */
142 //#define PROJ_FACE_INIT    (1<<1)  /* When we have initialized the faces data */
143 
144 /* If this face has a seam on any of its edges. */
145 #  define PROJ_FACE_SEAM0 (1 << 0)
146 #  define PROJ_FACE_SEAM1 (1 << 1)
147 #  define PROJ_FACE_SEAM2 (1 << 2)
148 
149 #  define PROJ_FACE_NOSEAM0 (1 << 4)
150 #  define PROJ_FACE_NOSEAM1 (1 << 5)
151 #  define PROJ_FACE_NOSEAM2 (1 << 6)
152 
153 /* If the seam is completely initialized, including adjecent seams. */
154 #  define PROJ_FACE_SEAM_INIT0 (1 << 8)
155 #  define PROJ_FACE_SEAM_INIT1 (1 << 9)
156 #  define PROJ_FACE_SEAM_INIT2 (1 << 10)
157 
158 #  define PROJ_FACE_DEGENERATE (1 << 12)
159 
160 /* face winding */
161 #  define PROJ_FACE_WINDING_INIT 1
162 #  define PROJ_FACE_WINDING_CW 2
163 
164 /* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
165  * as this number approaches  1.0f the likelihood increases of float precision errors where
166  * it is occluded by an adjacent face */
167 #  define PROJ_FACE_SCALE_SEAM 0.99f
168 #endif /* PROJ_DEBUG_NOSEAMBLEED */
169 
170 #define PROJ_SRC_VIEW 1
171 #define PROJ_SRC_IMAGE_CAM 2
172 #define PROJ_SRC_IMAGE_VIEW 3
173 #define PROJ_SRC_VIEW_FILL 4
174 
175 #define PROJ_VIEW_DATA_ID "view_data"
176 /* viewmat + winmat + clip_start + clip_end + is_ortho */
177 #define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3)
178 
179 #define PROJ_BUCKET_NULL 0
180 #define PROJ_BUCKET_INIT (1 << 0)
181 // #define PROJ_BUCKET_CLONE_INIT   (1<<1)
182 
183 /* used for testing doubles, if a point is on a line etc */
184 #define PROJ_GEOM_TOLERANCE 0.00075f
185 #define PROJ_PIXEL_TOLERANCE 0.01f
186 
187 /* vert flags */
188 #define PROJ_VERT_CULL 1
189 
190 /* to avoid locking in tile initialization */
191 #define TILE_PENDING POINTER_FROM_INT(-1)
192 
193 /**
194  * This is mainly a convenience struct used so we can keep an array of images we use -
195  * their imbufs, etc, in 1 array, When using threads this array is copied for each thread
196  * because 'partRedrawRect' and 'touch' values would not be thread safe.
197  */
198 typedef struct ProjPaintImage {
199   Image *ima;
200   ImageUser iuser;
201   ImBuf *ibuf;
202   ImagePaintPartialRedraw *partRedrawRect;
203   /** Only used to build undo tiles during painting. */
204   volatile void **undoRect;
205   /** The mask accumulation must happen on canvas, not on space screen bucket.
206    * Here we store the mask rectangle. */
207   ushort **maskRect;
208   /** Store flag to enforce validation of undo rectangle. */
209   bool **valid;
210   bool touch;
211 } ProjPaintImage;
212 
213 /**
214  * Handle for stroke (operator customdata)
215  */
216 typedef struct ProjStrokeHandle {
217   /* Support for painting from multiple views at once,
218    * currently used to implement symmetry painting,
219    * we can assume at least the first is set while painting. */
220   struct ProjPaintState *ps_views[8];
221   int ps_views_tot;
222   int symmetry_flags;
223 
224   int orig_brush_size;
225 
226   bool need_redraw;
227 
228   /* trick to bypass regular paint and allow clone picking */
229   bool is_clone_cursor_pick;
230 
231   /* In ProjPaintState, only here for convenience */
232   Scene *scene;
233   Brush *brush;
234 } ProjStrokeHandle;
235 
236 typedef struct LoopSeamData {
237   float seam_uvs[2][2];
238   float seam_puvs[2][2];
239   float corner_dist_sq[2];
240 } LoopSeamData;
241 
242 /* Main projection painting struct passed to all projection painting functions */
243 typedef struct ProjPaintState {
244   View3D *v3d;
245   RegionView3D *rv3d;
246   ARegion *region;
247   Depsgraph *depsgraph;
248   Scene *scene;
249   /* PROJ_SRC_**** */
250   int source;
251 
252   /* the paint color. It can change depending of inverted mode or not */
253   float paint_color[3];
254   float paint_color_linear[3];
255   float dither;
256 
257   Brush *brush;
258   short tool, blend, mode;
259 
260   float brush_size;
261   Object *ob;
262   /* for symmetry, we need to store modified object matrix */
263   float obmat[4][4];
264   float obmat_imat[4][4];
265   /* end similarities with ImagePaintState */
266 
267   Image *stencil_ima;
268   Image *canvas_ima;
269   Image *clone_ima;
270   float stencil_value;
271 
272   /* projection painting only */
273   /** for multithreading, the first item is sometimes used for non threaded cases too. */
274   MemArena *arena_mt[BLENDER_MAX_THREADS];
275   /** screen sized 2D array, each pixel has a linked list of ProjPixel's */
276   LinkNode **bucketRect;
277   /** bucketRect aligned array linkList of faces overlapping each bucket. */
278   LinkNode **bucketFaces;
279   /** store if the bucks have been initialized. */
280   uchar *bucketFlags;
281 
282   /** store options per vert, now only store if the vert is pointing away from the view. */
283   char *vertFlags;
284   /** The size of the bucket grid, the grid span's screenMin/screenMax
285    * so you can paint outsize the screen or with 2 brushes at once. */
286   int buckets_x;
287   int buckets_y;
288 
289   /** result of project_paint_pixel_sizeof(), constant per stroke. */
290   int pixel_sizeof;
291 
292   /** size of projectImages array. */
293   int image_tot;
294 
295   /** verts projected into floating point screen space. */
296   float (*screenCoords)[4];
297   /** 2D bounds for mesh verts on the screen's plane (screenspace). */
298   float screenMin[2];
299   float screenMax[2];
300   /** Calculated from screenMin & screenMax. */
301   float screen_width;
302   float screen_height;
303   /** from the carea or from the projection render. */
304   int winx, winy;
305 
306   /* options for projection painting */
307   bool do_layer_clone;
308   bool do_layer_stencil;
309   bool do_layer_stencil_inv;
310   bool do_stencil_brush;
311   bool do_material_slots;
312 
313   /** Use raytraced occlusion? - ortherwise will paint right through to the back. */
314   bool do_occlude;
315   /** ignore faces with normals pointing away,
316    * skips a lot of raycasts if your normals are correctly flipped. */
317   bool do_backfacecull;
318   /** mask out pixels based on their normals. */
319   bool do_mask_normal;
320   /** mask out pixels based on cavity. */
321   bool do_mask_cavity;
322   /** what angle to mask at. */
323   float normal_angle;
324   /** cos(normal_angle), faster to compare. */
325   float normal_angle__cos;
326   float normal_angle_inner;
327   float normal_angle_inner__cos;
328   /** difference between normal_angle and normal_angle_inner, for easy access. */
329   float normal_angle_range;
330 
331   /** quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */
332   bool do_face_sel;
333   bool is_ortho;
334   /** the object is negative scaled. */
335   bool is_flip_object;
336   /** use masking during painting. Some operations such as airbrush may disable. */
337   bool do_masking;
338   /** only to avoid running. */
339   bool is_texbrush;
340   /** mask brush is applied before masking. */
341   bool is_maskbrush;
342 #ifndef PROJ_DEBUG_NOSEAMBLEED
343   float seam_bleed_px;
344   float seam_bleed_px_sq;
345 #endif
346   /* clone vars */
347   float cloneOffset[2];
348 
349   /** Projection matrix, use for getting screen coords. */
350   float projectMat[4][4];
351   /** inverse of projectMat. */
352   float projectMatInv[4][4];
353   /** View vector, use for do_backfacecull and for ray casting with an ortho viewport. */
354   float viewDir[3];
355   /** View location in object relative 3D space, so can compare to verts. */
356   float viewPos[3];
357   float clip_start, clip_end;
358 
359   /* reproject vars */
360   Image *reproject_image;
361   ImBuf *reproject_ibuf;
362   bool reproject_ibuf_free_float;
363   bool reproject_ibuf_free_uchar;
364 
365   /* threads */
366   int thread_tot;
367   int bucketMin[2];
368   int bucketMax[2];
369   /** must lock threads while accessing these. */
370   int context_bucket_index;
371 
372   struct CurveMapping *cavity_curve;
373   BlurKernel *blurkernel;
374 
375   /* -------------------------------------------------------------------- */
376   /* Vars shared between multiple views (keep last) */
377   /**
378    * This data is owned by ``ProjStrokeHandle.ps_views[0]``,
379    * all other views re-use the data.
380    */
381 
382 #define PROJ_PAINT_STATE_SHARED_MEMCPY(ps_dst, ps_src) \
383   MEMCPY_STRUCT_AFTER(ps_dst, ps_src, is_shared_user)
384 
385 #define PROJ_PAINT_STATE_SHARED_CLEAR(ps) MEMSET_STRUCT_AFTER(ps, 0, is_shared_user)
386 
387   bool is_shared_user;
388 
389   ProjPaintImage *projImages;
390   /** cavity amount for vertices. */
391   float *cavities;
392 
393 #ifndef PROJ_DEBUG_NOSEAMBLEED
394   /** store info about faces, if they are initialized etc*/
395   ushort *faceSeamFlags;
396   /** save the winding of the face in uv space,
397    * helps as an extra validation step for seam detection. */
398   char *faceWindingFlags;
399   /** expanded UVs for faces to use as seams. */
400   LoopSeamData *loopSeamData;
401   /** Only needed for when seam_bleed_px is enabled, use to find UV seams. */
402   LinkNode **vertFaces;
403   /** Seams per vert, to find adjacent seams. */
404   ListBase *vertSeams;
405 #endif
406 
407   SpinLock *tile_lock;
408 
409   Mesh *me_eval;
410   int totlooptri_eval;
411   int totloop_eval;
412   int totpoly_eval;
413   int totedge_eval;
414   int totvert_eval;
415 
416   const MVert *mvert_eval;
417   const MEdge *medge_eval;
418   const MPoly *mpoly_eval;
419   const MLoop *mloop_eval;
420   const MLoopTri *mlooptri_eval;
421 
422   const MLoopUV *mloopuv_stencil_eval;
423 
424   /**
425    * \note These UV layers are aligned to \a mpoly_eval
426    * but each pointer references the start of the layer,
427    * so a loop indirection is needed as well.
428    */
429   const MLoopUV **poly_to_loop_uv;
430   /** other UV map, use for cloning between layers. */
431   const MLoopUV **poly_to_loop_uv_clone;
432 
433   /* Actual material for each index, either from object or Mesh datablock... */
434   Material **mat_array;
435 
436   bool use_colormanagement;
437 } ProjPaintState;
438 
439 typedef union pixelPointer {
440   /** float buffer. */
441   float *f_pt;
442   /** 2 ways to access a char buffer. */
443   uint *uint_pt;
444   uchar *ch_pt;
445 } PixelPointer;
446 
447 typedef union pixelStore {
448   uchar ch[4];
449   uint uint;
450   float f[4];
451 } PixelStore;
452 
453 typedef struct ProjPixel {
454   /** the floating point screen projection of this pixel. */
455   float projCoSS[2];
456   float worldCoSS[3];
457 
458   short x_px, y_px;
459 
460   /** if anyone wants to paint onto more than 65535 images they can bite me. */
461   ushort image_index;
462   uchar bb_cell_index;
463 
464   /* for various reasons we may want to mask out painting onto this pixel */
465   ushort mask;
466 
467   /* Only used when the airbrush is disabled.
468    * Store the max mask value to avoid painting over an area with a lower opacity
469    * with an advantage that we can avoid touching the pixel at all, if the
470    * new mask value is lower than mask_accum */
471   ushort *mask_accum;
472 
473   /* horrible hack, store tile valid flag pointer here to re-validate tiles
474    * used for anchored and drag-dot strokes */
475   bool *valid;
476 
477   PixelPointer origColor;
478   PixelStore newColor;
479   PixelPointer pixel;
480 } ProjPixel;
481 
482 typedef struct ProjPixelClone {
483   struct ProjPixel __pp;
484   PixelStore clonepx;
485 } ProjPixelClone;
486 
487 /* undo tile pushing */
488 typedef struct {
489   SpinLock *lock;
490   bool masked;
491   ushort tile_width;
492   ImBuf **tmpibuf;
493   ProjPaintImage *pjima;
494 } TileInfo;
495 
496 typedef struct VertSeam {
497   struct VertSeam *next, *prev;
498   int tri;
499   uint loop;
500   float angle;
501   bool normal_cw;
502   float uv[2];
503 } VertSeam;
504 
505 /* -------------------------------------------------------------------- */
506 /** \name MLoopTri accessor functions.
507  * \{ */
508 
ps_tri_index_to_mpoly(const ProjPaintState * ps,int tri_index)509 BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index)
510 {
511   return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly];
512 }
513 
514 #define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \
515   ps->mloop_eval[lt->tri[0]].v, ps->mloop_eval[lt->tri[1]].v, ps->mloop_eval[lt->tri[2]].v,
516 
517 #define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
518   uvlayer[lt->poly][lt->tri[0]].uv, uvlayer[lt->poly][lt->tri[1]].uv, \
519       uvlayer[lt->poly][lt->tri[2]].uv,
520 
521 #define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) \
522   { \
523     (uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]].uv; \
524     (uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]].uv; \
525     (uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]].uv; \
526   } \
527   ((void)0)
528 
529 /** \} */
530 
531 /* Finish projection painting structs */
532 
project_paint_face_paint_tile(Image * ima,const float * uv)533 static int project_paint_face_paint_tile(Image *ima, const float *uv)
534 {
535   if (ima == NULL || ima->source != IMA_SRC_TILED) {
536     return 0;
537   }
538 
539   /* Currently, faces are assumed to belong to one tile, so checking the first loop is enough. */
540   int tx = (int)uv[0];
541   int ty = (int)uv[1];
542   return 1001 + 10 * ty + tx;
543 }
544 
project_paint_face_paint_slot(const ProjPaintState * ps,int tri_index)545 static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
546 {
547   const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
548   Material *ma = ps->mat_array[mp->mat_nr];
549   return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
550 }
551 
project_paint_face_paint_image(const ProjPaintState * ps,int tri_index)552 static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_index)
553 {
554   if (ps->do_stencil_brush) {
555     return ps->stencil_ima;
556   }
557 
558   const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
559   Material *ma = ps->mat_array[mp->mat_nr];
560   TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
561   return slot ? slot->ima : ps->canvas_ima;
562 }
563 
project_paint_face_clone_slot(const ProjPaintState * ps,int tri_index)564 static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
565 {
566   const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
567   Material *ma = ps->mat_array[mp->mat_nr];
568   return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
569 }
570 
project_paint_face_clone_image(const ProjPaintState * ps,int tri_index)571 static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
572 {
573   const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
574   Material *ma = ps->mat_array[mp->mat_nr];
575   TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
576   return slot ? slot->ima : ps->clone_ima;
577 }
578 
579 /* fast projection bucket array lookup, use the safe version for bound checking  */
project_bucket_offset(const ProjPaintState * ps,const float projCoSS[2])580 static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2])
581 {
582   /* If we were not dealing with screenspace 2D coords we could simple do...
583    * ps->bucketRect[x + (y*ps->buckets_y)] */
584 
585   /* please explain?
586    * projCoSS[0] - ps->screenMin[0]   : zero origin
587    * ... / ps->screen_width           : range from 0.0 to 1.0
588    * ... * ps->buckets_x              : use as a bucket index
589    *
590    * Second multiplication does similar but for vertical offset
591    */
592   return ((int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) +
593          (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) *
594           ps->buckets_x);
595 }
596 
project_bucket_offset_safe(const ProjPaintState * ps,const float projCoSS[2])597 static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2])
598 {
599   int bucket_index = project_bucket_offset(ps, projCoSS);
600 
601   if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) {
602     return -1;
603   }
604   return bucket_index;
605 }
606 
VecZDepthOrtho(const float pt[2],const float v1[3],const float v2[3],const float v3[3],float w[3])607 static float VecZDepthOrtho(
608     const float pt[2], const float v1[3], const float v2[3], const float v3[3], float w[3])
609 {
610   barycentric_weights_v2(v1, v2, v3, pt, w);
611   return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]);
612 }
613 
VecZDepthPersp(const float pt[2],const float v1[4],const float v2[4],const float v3[4],float w[3])614 static float VecZDepthPersp(
615     const float pt[2], const float v1[4], const float v2[4], const float v3[4], float w[3])
616 {
617   float wtot_inv, wtot;
618   float w_tmp[3];
619 
620   barycentric_weights_v2_persp(v1, v2, v3, pt, w);
621   /* for the depth we need the weights to match what
622    * barycentric_weights_v2 would return, in this case its easiest just to
623    * undo the 4th axis division and make it unit-sum
624    *
625    * don't call barycentric_weights_v2() because our callers expect 'w'
626    * to be weighted from the perspective */
627   w_tmp[0] = w[0] * v1[3];
628   w_tmp[1] = w[1] * v2[3];
629   w_tmp[2] = w[2] * v3[3];
630 
631   wtot = w_tmp[0] + w_tmp[1] + w_tmp[2];
632 
633   if (wtot != 0.0f) {
634     wtot_inv = 1.0f / wtot;
635 
636     w_tmp[0] = w_tmp[0] * wtot_inv;
637     w_tmp[1] = w_tmp[1] * wtot_inv;
638     w_tmp[2] = w_tmp[2] * wtot_inv;
639   }
640   else { /* dummy values for zero area face */
641     w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f;
642   }
643   /* done mimicking barycentric_weights_v2() */
644 
645   return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[2]);
646 }
647 
648 /* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
project_paint_PickFace(const ProjPaintState * ps,const float pt[2],float w[3])649 static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3])
650 {
651   LinkNode *node;
652   float w_tmp[3];
653   int bucket_index;
654   int best_tri_index = -1;
655   float z_depth_best = FLT_MAX, z_depth;
656 
657   bucket_index = project_bucket_offset_safe(ps, pt);
658   if (bucket_index == -1) {
659     return -1;
660   }
661 
662   /* we could return 0 for 1 face buckets, as long as this function assumes
663    * that the point its testing is only every originated from an existing face */
664 
665   for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
666     const int tri_index = POINTER_AS_INT(node->link);
667     const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
668     const float *vtri_ss[3] = {
669         ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
670         ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
671         ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
672     };
673 
674     if (isect_point_tri_v2(pt, UNPACK3(vtri_ss))) {
675       if (ps->is_ortho) {
676         z_depth = VecZDepthOrtho(pt, UNPACK3(vtri_ss), w_tmp);
677       }
678       else {
679         z_depth = VecZDepthPersp(pt, UNPACK3(vtri_ss), w_tmp);
680       }
681 
682       if (z_depth < z_depth_best) {
683         best_tri_index = tri_index;
684         z_depth_best = z_depth;
685         copy_v3_v3(w, w_tmp);
686       }
687     }
688   }
689 
690   /** will be -1 or a valid face. */
691   return best_tri_index;
692 }
693 
694 /* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
uvco_to_wrapped_pxco(const float uv[2],int ibuf_x,int ibuf_y,float * x,float * y)695 static void uvco_to_wrapped_pxco(const float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
696 {
697   /* use */
698   *x = fmodf(uv[0], 1.0f);
699   *y = fmodf(uv[1], 1.0f);
700 
701   if (*x < 0.0f) {
702     *x += 1.0f;
703   }
704   if (*y < 0.0f) {
705     *y += 1.0f;
706   }
707 
708   *x = *x * ibuf_x - 0.5f;
709   *y = *y * ibuf_y - 0.5f;
710 }
711 
712 /* Set the top-most face color that the screen space coord 'pt' touches
713  * (or return 0 if none touch) */
project_paint_PickColor(const ProjPaintState * ps,const float pt[2],float * rgba_fp,uchar * rgba,const bool interp)714 static bool project_paint_PickColor(
715     const ProjPaintState *ps, const float pt[2], float *rgba_fp, uchar *rgba, const bool interp)
716 {
717   const MLoopTri *lt;
718   const float *lt_tri_uv[3];
719   float w[3], uv[2];
720   int tri_index;
721   Image *ima;
722   ImBuf *ibuf;
723   int xi, yi;
724 
725   tri_index = project_paint_PickFace(ps, pt, w);
726 
727   if (tri_index == -1) {
728     return false;
729   }
730 
731   lt = &ps->mlooptri_eval[tri_index];
732   PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
733 
734   interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
735 
736   ima = project_paint_face_paint_image(ps, tri_index);
737   /** we must have got the imbuf before getting here. */
738   int tile_number = project_paint_face_paint_tile(ima, lt_tri_uv[0]);
739   /* XXX get appropriate ImageUser instead */
740   ImageUser iuser;
741   BKE_imageuser_default(&iuser);
742   iuser.tile = tile_number;
743   iuser.framenr = ima->lastframe;
744   ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
745   if (ibuf == NULL) {
746     return false;
747   }
748 
749   if (interp) {
750     float x, y;
751     uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
752 
753     if (ibuf->rect_float) {
754       if (rgba_fp) {
755         bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
756       }
757       else {
758         float rgba_tmp_f[4];
759         bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
760         premul_float_to_straight_uchar(rgba, rgba_tmp_f);
761       }
762     }
763     else {
764       if (rgba) {
765         bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
766       }
767       else {
768         uchar rgba_tmp[4];
769         bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
770         straight_uchar_to_premul_float(rgba_fp, rgba_tmp);
771       }
772     }
773   }
774   else {
775     // xi = (int)((uv[0]*ibuf->x) + 0.5f);
776     // yi = (int)((uv[1]*ibuf->y) + 0.5f);
777     // if (xi < 0 || xi >= ibuf->x  ||  yi < 0 || yi >= ibuf->y) return false;
778 
779     /* wrap */
780     xi = mod_i((int)(uv[0] * ibuf->x), ibuf->x);
781     yi = mod_i((int)(uv[1] * ibuf->y), ibuf->y);
782 
783     if (rgba) {
784       if (ibuf->rect_float) {
785         const float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
786         premul_float_to_straight_uchar(rgba, rgba_tmp_fp);
787       }
788       else {
789         *((uint *)rgba) = *(uint *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
790       }
791     }
792 
793     if (rgba_fp) {
794       if (ibuf->rect_float) {
795         copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
796       }
797       else {
798         uchar *tmp_ch = ((uchar *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
799         straight_uchar_to_premul_float(rgba_fp, tmp_ch);
800       }
801     }
802   }
803   BKE_image_release_ibuf(ima, ibuf, NULL);
804   return true;
805 }
806 
807 /**
808  * Check if 'pt' is in front of the 3 verts on the Z axis (used for screen-space occlusion test)
809  * \return
810  * -  `0`:   no occlusion
811  * - `-1`: no occlusion but 2D intersection is true
812  * -  `1`: occluded
813  * -  `2`: occluded with `w[3]` weights set (need to know in some cases)
814  */
project_paint_occlude_ptv(const float pt[3],const float v1[4],const float v2[4],const float v3[4],float w[3],const bool is_ortho)815 static int project_paint_occlude_ptv(const float pt[3],
816                                      const float v1[4],
817                                      const float v2[4],
818                                      const float v3[4],
819                                      float w[3],
820                                      const bool is_ortho)
821 {
822   /* if all are behind us, return false */
823   if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2]) {
824     return 0;
825   }
826 
827   /* do a 2D point in try intersection */
828   if (!isect_point_tri_v2(pt, v1, v2, v3)) {
829     return 0;
830   }
831 
832   /* From here on we know there IS an intersection */
833   /* if ALL of the verts are in front of us then we know it intersects ? */
834   if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
835     return 1;
836   }
837 
838   /* we intersect? - find the exact depth at the point of intersection */
839   /* Is this point is occluded by another face? */
840   if (is_ortho) {
841     if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) {
842       return 2;
843     }
844   }
845   else {
846     if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) {
847       return 2;
848     }
849   }
850   return -1;
851 }
852 
project_paint_occlude_ptv_clip(const float pt[3],const float v1[4],const float v2[4],const float v3[4],const float v1_3d[3],const float v2_3d[3],const float v3_3d[3],float w[3],const bool is_ortho,RegionView3D * rv3d)853 static int project_paint_occlude_ptv_clip(const float pt[3],
854                                           const float v1[4],
855                                           const float v2[4],
856                                           const float v3[4],
857                                           const float v1_3d[3],
858                                           const float v2_3d[3],
859                                           const float v3_3d[3],
860                                           float w[3],
861                                           const bool is_ortho,
862                                           RegionView3D *rv3d)
863 {
864   float wco[3];
865   int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, is_ortho);
866 
867   if (ret <= 0) {
868     return ret;
869   }
870 
871   if (ret == 1) { /* weights not calculated */
872     if (is_ortho) {
873       barycentric_weights_v2(v1, v2, v3, pt, w);
874     }
875     else {
876       barycentric_weights_v2_persp(v1, v2, v3, pt, w);
877     }
878   }
879 
880   /* Test if we're in the clipped area, */
881   interp_v3_v3v3v3(wco, v1_3d, v2_3d, v3_3d, w);
882 
883   if (!ED_view3d_clipping_test(rv3d, wco, true)) {
884     return 1;
885   }
886 
887   return -1;
888 }
889 
890 /* Check if a screenspace location is occluded by any other faces
891  * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
892  * and doesn't need to be correct in relation to X and Y coords
893  * (this is the case in perspective view) */
project_bucket_point_occluded(const ProjPaintState * ps,LinkNode * bucketFace,const int orig_face,const float pixelScreenCo[4])894 static bool project_bucket_point_occluded(const ProjPaintState *ps,
895                                           LinkNode *bucketFace,
896                                           const int orig_face,
897                                           const float pixelScreenCo[4])
898 {
899   int isect_ret;
900   const bool do_clip = RV3D_CLIPPING_ENABLED(ps->v3d, ps->rv3d);
901 
902   /* we could return false for 1 face buckets, as long as this function assumes
903    * that the point its testing is only every originated from an existing face */
904 
905   for (; bucketFace; bucketFace = bucketFace->next) {
906     const int tri_index = POINTER_AS_INT(bucketFace->link);
907 
908     if (orig_face != tri_index) {
909       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
910       const float *vtri_ss[3] = {
911           ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
912           ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
913           ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
914       };
915       float w[3];
916 
917       if (do_clip) {
918         const float *vtri_co[3] = {
919             ps->mvert_eval[ps->mloop_eval[lt->tri[0]].v].co,
920             ps->mvert_eval[ps->mloop_eval[lt->tri[1]].v].co,
921             ps->mvert_eval[ps->mloop_eval[lt->tri[2]].v].co,
922         };
923         isect_ret = project_paint_occlude_ptv_clip(
924             pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co), w, ps->is_ortho, ps->rv3d);
925       }
926       else {
927         isect_ret = project_paint_occlude_ptv(pixelScreenCo, UNPACK3(vtri_ss), w, ps->is_ortho);
928       }
929 
930       if (isect_ret >= 1) {
931         /* TODO - we may want to cache the first hit,
932          * it is not possible to swap the face order in the list anymore */
933         return true;
934       }
935     }
936   }
937   return false;
938 }
939 
940 /* Basic line intersection, could move to math_geom.c, 2 points with a horizontal line
941  * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned. */
942 #define ISECT_TRUE 1
943 #define ISECT_TRUE_P1 2
944 #define ISECT_TRUE_P2 3
line_isect_y(const float p1[2],const float p2[2],const float y_level,float * x_isect)945 static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect)
946 {
947   float y_diff;
948 
949   /* are we touching the first point? - no interpolation needed */
950   if (y_level == p1[1]) {
951     *x_isect = p1[0];
952     return ISECT_TRUE_P1;
953   }
954   /* are we touching the second point? - no interpolation needed */
955   if (y_level == p2[1]) {
956     *x_isect = p2[0];
957     return ISECT_TRUE_P2;
958   }
959 
960   /** yuck, horizontal line, we cant do much here. */
961   y_diff = fabsf(p1[1] - p2[1]);
962 
963   if (y_diff < 0.000001f) {
964     *x_isect = (p1[0] + p2[0]) * 0.5f;
965     return ISECT_TRUE;
966   }
967 
968   if (p1[1] > y_level && p2[1] < y_level) {
969     /* (p1[1] - p2[1]); */
970     *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff;
971     return ISECT_TRUE;
972   }
973   if (p1[1] < y_level && p2[1] > y_level) {
974     /* (p2[1] - p1[1]); */
975     *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff;
976     return ISECT_TRUE;
977   }
978   return 0;
979 }
980 
line_isect_x(const float p1[2],const float p2[2],const float x_level,float * y_isect)981 static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect)
982 {
983   float x_diff;
984 
985   if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */
986     *y_isect = p1[1];
987     return ISECT_TRUE_P1;
988   }
989   if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */
990     *y_isect = p2[1];
991     return ISECT_TRUE_P2;
992   }
993 
994   /* yuck, horizontal line, we cant do much here */
995   x_diff = fabsf(p1[0] - p2[0]);
996 
997   /* yuck, vertical line, we cant do much here */
998   if (x_diff < 0.000001f) {
999     *y_isect = (p1[0] + p2[0]) * 0.5f;
1000     return ISECT_TRUE;
1001   }
1002 
1003   if (p1[0] > x_level && p2[0] < x_level) {
1004     /* (p1[0] - p2[0]); */
1005     *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff;
1006     return ISECT_TRUE;
1007   }
1008   if (p1[0] < x_level && p2[0] > x_level) {
1009     /* (p2[0] - p1[0]); */
1010     *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff;
1011     return ISECT_TRUE;
1012   }
1013   return 0;
1014 }
1015 
1016 /* simple func use for comparing UV locations to check if there are seams.
1017  * Its possible this gives incorrect results, when the UVs for 1 face go into the next
1018  * tile, but do not do this for the adjacent face, it could return a false positive.
1019  * This is so unlikely that Id not worry about it. */
1020 #ifndef PROJ_DEBUG_NOSEAMBLEED
cmp_uv(const float vec2a[2],const float vec2b[2])1021 static bool cmp_uv(const float vec2a[2], const float vec2b[2])
1022 {
1023   /* if the UV's are not between 0.0 and 1.0 */
1024   float xa = fmodf(vec2a[0], 1.0f);
1025   float ya = fmodf(vec2a[1], 1.0f);
1026 
1027   float xb = fmodf(vec2b[0], 1.0f);
1028   float yb = fmodf(vec2b[1], 1.0f);
1029 
1030   if (xa < 0.0f) {
1031     xa += 1.0f;
1032   }
1033   if (ya < 0.0f) {
1034     ya += 1.0f;
1035   }
1036 
1037   if (xb < 0.0f) {
1038     xb += 1.0f;
1039   }
1040   if (yb < 0.0f) {
1041     yb += 1.0f;
1042   }
1043 
1044   return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ?
1045              true :
1046              false;
1047 }
1048 #endif
1049 
1050 /* set min_px and max_px to the image space bounds of the UV coords
1051  * return zero if there is no area in the returned rectangle */
1052 #ifndef PROJ_DEBUG_NOSEAMBLEED
pixel_bounds_uv(const float uv_quad[4][2],rcti * bounds_px,const int ibuf_x,const int ibuf_y)1053 static bool pixel_bounds_uv(const float uv_quad[4][2],
1054                             rcti *bounds_px,
1055                             const int ibuf_x,
1056                             const int ibuf_y)
1057 {
1058   /* UV bounds */
1059   float min_uv[2], max_uv[2];
1060 
1061   INIT_MINMAX2(min_uv, max_uv);
1062 
1063   minmax_v2v2_v2(min_uv, max_uv, uv_quad[0]);
1064   minmax_v2v2_v2(min_uv, max_uv, uv_quad[1]);
1065   minmax_v2v2_v2(min_uv, max_uv, uv_quad[2]);
1066   minmax_v2v2_v2(min_uv, max_uv, uv_quad[3]);
1067 
1068   bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
1069   bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
1070 
1071   bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
1072   bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
1073 
1074   /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
1075 
1076   /* face uses no UV area when quantized to pixels? */
1077   return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? false : true;
1078 }
1079 #endif
1080 
pixel_bounds_array(float (* uv)[2],rcti * bounds_px,const int ibuf_x,const int ibuf_y,int tot)1081 static bool pixel_bounds_array(
1082     float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
1083 {
1084   /* UV bounds */
1085   float min_uv[2], max_uv[2];
1086 
1087   if (tot == 0) {
1088     return false;
1089   }
1090 
1091   INIT_MINMAX2(min_uv, max_uv);
1092 
1093   while (tot--) {
1094     minmax_v2v2_v2(min_uv, max_uv, (*uv));
1095     uv++;
1096   }
1097 
1098   bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
1099   bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
1100 
1101   bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1;
1102   bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1;
1103 
1104   /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
1105 
1106   /* face uses no UV area when quantized to pixels? */
1107   return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? false : true;
1108 }
1109 
1110 #ifndef PROJ_DEBUG_NOSEAMBLEED
1111 
project_face_winding_init(const ProjPaintState * ps,const int tri_index)1112 static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
1113 {
1114   /* detect the winding of faces in uv space */
1115   const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
1116   const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
1117   float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
1118 
1119   if (winding > 0) {
1120     ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_CW;
1121   }
1122 
1123   ps->faceWindingFlags[tri_index] |= PROJ_FACE_WINDING_INIT;
1124 }
1125 
1126 /* This function returns 1 if this face has a seam along the 2 face-vert indices
1127  * 'orig_i1_fidx' and 'orig_i2_fidx' */
check_seam(const ProjPaintState * ps,const int orig_face,const int orig_i1_fidx,const int orig_i2_fidx,int * other_face,int * orig_fidx)1128 static bool check_seam(const ProjPaintState *ps,
1129                        const int orig_face,
1130                        const int orig_i1_fidx,
1131                        const int orig_i2_fidx,
1132                        int *other_face,
1133                        int *orig_fidx)
1134 {
1135   const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face];
1136   const float *orig_lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt)};
1137   /* vert indices from face vert order indices */
1138   const uint i1 = ps->mloop_eval[orig_lt->tri[orig_i1_fidx]].v;
1139   const uint i2 = ps->mloop_eval[orig_lt->tri[orig_i2_fidx]].v;
1140   LinkNode *node;
1141   /* index in face */
1142   int i1_fidx = -1, i2_fidx = -1;
1143 
1144   for (node = ps->vertFaces[i1]; node; node = node->next) {
1145     const int tri_index = POINTER_AS_INT(node->link);
1146 
1147     if (tri_index != orig_face) {
1148       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
1149       const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
1150       /* could check if the 2 faces images match here,
1151        * but then there wouldn't be a way to return the opposite face's info */
1152 
1153       /* We need to know the order of the verts in the adjacent face
1154        * set the i1_fidx and i2_fidx to (0,1,2,3) */
1155       i1_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i1);
1156       i2_fidx = BKE_MESH_TESSTRI_VINDEX_ORDER(lt_vtri, i2);
1157 
1158       /* Only need to check if 'i2_fidx' is valid because
1159        * we know i1_fidx is the same vert on both faces. */
1160       if (i2_fidx != -1) {
1161         const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
1162         Image *tpage = project_paint_face_paint_image(ps, tri_index);
1163         Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
1164         int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
1165         int orig_tile = project_paint_face_paint_tile(orig_tpage, orig_lt_tri_uv[0]);
1166 
1167         BLI_assert(i1_fidx != -1);
1168 
1169         /* This IS an adjacent face!, now lets check if the UVs are ok */
1170 
1171         /* set up the other face */
1172         *other_face = tri_index;
1173 
1174         /* we check if difference is 1 here, else we might have a case of edge 2-0 for a tri */
1175         *orig_fidx = (i1_fidx < i2_fidx && (i2_fidx - i1_fidx == 1)) ? i1_fidx : i2_fidx;
1176 
1177         /* initialize face winding if needed */
1178         if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0) {
1179           project_face_winding_init(ps, tri_index);
1180         }
1181 
1182         /* first test if they have the same image */
1183         if ((orig_tpage == tpage) && (orig_tile == tile) &&
1184             cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
1185             cmp_uv(orig_lt_tri_uv[orig_i2_fidx], lt_tri_uv[i2_fidx])) {
1186           /* if faces don't have the same winding in uv space,
1187            * they are on the same side so edge is boundary */
1188           if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW) !=
1189               (ps->faceWindingFlags[orig_face] & PROJ_FACE_WINDING_CW)) {
1190             return true;
1191           }
1192 
1193           // printf("SEAM (NONE)\n");
1194           return false;
1195         }
1196         // printf("SEAM (UV GAP)\n");
1197         return true;
1198       }
1199     }
1200   }
1201   // printf("SEAM (NO FACE)\n");
1202   *other_face = -1;
1203   return true;
1204 }
1205 
find_adjacent_seam(const ProjPaintState * ps,uint loop_index,uint vert_index,VertSeam ** r_seam)1206 static VertSeam *find_adjacent_seam(const ProjPaintState *ps,
1207                                     uint loop_index,
1208                                     uint vert_index,
1209                                     VertSeam **r_seam)
1210 {
1211   ListBase *vert_seams = &ps->vertSeams[vert_index];
1212   VertSeam *seam = vert_seams->first;
1213   VertSeam *adjacent = NULL;
1214 
1215   while (seam->loop != loop_index) {
1216     seam = seam->next;
1217   }
1218 
1219   if (r_seam) {
1220     *r_seam = seam;
1221   }
1222 
1223   /* Circulate through the (sorted) vert seam array, in the direction of the seam normal,
1224    * until we find the first opposing seam, matching in UV space. */
1225   if (seam->normal_cw) {
1226     LISTBASE_CIRCULAR_BACKWARD_BEGIN (vert_seams, adjacent, seam) {
1227       if ((adjacent->normal_cw != seam->normal_cw) && cmp_uv(adjacent->uv, seam->uv)) {
1228         break;
1229       }
1230     }
1231     LISTBASE_CIRCULAR_BACKWARD_END(vert_seams, adjacent, seam);
1232   }
1233   else {
1234     LISTBASE_CIRCULAR_FORWARD_BEGIN (vert_seams, adjacent, seam) {
1235       if ((adjacent->normal_cw != seam->normal_cw) && cmp_uv(adjacent->uv, seam->uv)) {
1236         break;
1237       }
1238     }
1239     LISTBASE_CIRCULAR_FORWARD_END(vert_seams, adjacent, seam);
1240   }
1241 
1242   BLI_assert(adjacent);
1243 
1244   return adjacent;
1245 }
1246 
1247 /* Computes the normal of two seams at their intersection,
1248  * and returns the angle between the seam and its normal. */
compute_seam_normal(VertSeam * seam,VertSeam * adj,float r_no[2])1249 static float compute_seam_normal(VertSeam *seam, VertSeam *adj, float r_no[2])
1250 {
1251   const float PI_2 = M_PI * 2.0f;
1252   float angle[2];
1253   float angle_rel, angle_no;
1254 
1255   if (seam->normal_cw) {
1256     angle[0] = adj->angle;
1257     angle[1] = seam->angle;
1258   }
1259   else {
1260     angle[0] = seam->angle;
1261     angle[1] = adj->angle;
1262   }
1263 
1264   angle_rel = angle[1] - angle[0];
1265 
1266   if (angle_rel < 0.0f) {
1267     angle_rel += PI_2;
1268   }
1269 
1270   angle_rel *= 0.5f;
1271 
1272   angle_no = angle_rel + angle[0];
1273 
1274   if (angle_no > M_PI) {
1275     angle_no -= PI_2;
1276   }
1277 
1278   r_no[0] = cosf(angle_no);
1279   r_no[1] = sinf(angle_no);
1280 
1281   return angle_rel;
1282 }
1283 
1284 /* Calculate outset UV's, this is not the same as simply scaling the UVs,
1285  * since the outset coords are a margin that keep an even distance from the original UV's,
1286  * note that the image aspect is taken into account */
uv_image_outset(const ProjPaintState * ps,float (* orig_uv)[2],float (* puv)[2],uint tri_index,const int ibuf_x,const int ibuf_y)1287 static void uv_image_outset(const ProjPaintState *ps,
1288                             float (*orig_uv)[2],
1289                             float (*puv)[2],
1290                             uint tri_index,
1291                             const int ibuf_x,
1292                             const int ibuf_y)
1293 {
1294   int fidx[2];
1295   uint loop_index;
1296   uint vert[2];
1297   const MLoopTri *ltri = &ps->mlooptri_eval[tri_index];
1298 
1299   float ibuf_inv[2];
1300 
1301   ibuf_inv[0] = 1.0f / (float)ibuf_x;
1302   ibuf_inv[1] = 1.0f / (float)ibuf_y;
1303 
1304   for (fidx[0] = 0; fidx[0] < 3; fidx[0]++) {
1305     LoopSeamData *seam_data;
1306     float(*seam_uvs)[2];
1307     float ang[2];
1308 
1309     if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM0 << fidx[0])) == 0) {
1310       continue;
1311     }
1312 
1313     loop_index = ltri->tri[fidx[0]];
1314 
1315     seam_data = &ps->loopSeamData[loop_index];
1316     seam_uvs = seam_data->seam_uvs;
1317 
1318     if (seam_uvs[0][0] != FLT_MAX) {
1319       continue;
1320     }
1321 
1322     fidx[1] = (fidx[0] == 2) ? 0 : fidx[0] + 1;
1323 
1324     vert[0] = ps->mloop_eval[loop_index].v;
1325     vert[1] = ps->mloop_eval[ltri->tri[fidx[1]]].v;
1326 
1327     for (uint i = 0; i < 2; i++) {
1328       VertSeam *seam;
1329       VertSeam *adj = find_adjacent_seam(ps, loop_index, vert[i], &seam);
1330       float no[2];
1331       float len_fact;
1332       float tri_ang;
1333 
1334       ang[i] = compute_seam_normal(seam, adj, no);
1335       tri_ang = ang[i] - M_PI_2;
1336 
1337       if (tri_ang > 0.0f) {
1338         const float dist = ps->seam_bleed_px * tanf(tri_ang);
1339         seam_data->corner_dist_sq[i] = square_f(dist);
1340       }
1341       else {
1342         seam_data->corner_dist_sq[i] = 0.0f;
1343       }
1344 
1345       len_fact = cosf(tri_ang);
1346       len_fact = UNLIKELY(len_fact < FLT_EPSILON) ? FLT_MAX : (1.0f / len_fact);
1347 
1348       /* Clamp the length factor, see: T62236. */
1349       len_fact = MIN2(len_fact, 10.0f);
1350 
1351       mul_v2_fl(no, ps->seam_bleed_px * len_fact);
1352 
1353       add_v2_v2v2(seam_data->seam_puvs[i], puv[fidx[i]], no);
1354 
1355       mul_v2_v2v2(seam_uvs[i], seam_data->seam_puvs[i], ibuf_inv);
1356     }
1357 
1358     /* Handle convergent normals (can self-intersect). */
1359     if ((ang[0] + ang[1]) < M_PI) {
1360       if (isect_seg_seg_v2_simple(orig_uv[fidx[0]], seam_uvs[0], orig_uv[fidx[1]], seam_uvs[1])) {
1361         float isect_co[2];
1362 
1363         isect_seg_seg_v2_point(
1364             orig_uv[fidx[0]], seam_uvs[0], orig_uv[fidx[1]], seam_uvs[1], isect_co);
1365 
1366         copy_v2_v2(seam_uvs[0], isect_co);
1367         copy_v2_v2(seam_uvs[1], isect_co);
1368       }
1369     }
1370   }
1371 }
1372 
insert_seam_vert_array(const ProjPaintState * ps,MemArena * arena,const int tri_index,const int fidx1,const int ibuf_x,const int ibuf_y)1373 static void insert_seam_vert_array(const ProjPaintState *ps,
1374                                    MemArena *arena,
1375                                    const int tri_index,
1376                                    const int fidx1,
1377                                    const int ibuf_x,
1378                                    const int ibuf_y)
1379 {
1380   const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
1381   const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
1382   const int fidx[2] = {fidx1, ((fidx1 + 1) % 3)};
1383   float vec[2];
1384 
1385   VertSeam *vseam = BLI_memarena_alloc(arena, sizeof(VertSeam[2]));
1386 
1387   vseam->prev = NULL;
1388   vseam->next = NULL;
1389 
1390   vseam->tri = tri_index;
1391   vseam->loop = lt->tri[fidx[0]];
1392 
1393   sub_v2_v2v2(vec, lt_tri_uv[fidx[1]], lt_tri_uv[fidx[0]]);
1394   vec[0] *= ibuf_x;
1395   vec[1] *= ibuf_y;
1396   vseam->angle = atan2f(vec[1], vec[0]);
1397 
1398   /* If face windings are not initialized, something must be wrong. */
1399   BLI_assert((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) != 0);
1400   vseam->normal_cw = (ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_CW);
1401 
1402   copy_v2_v2(vseam->uv, lt_tri_uv[fidx[0]]);
1403 
1404   vseam[1] = vseam[0];
1405   vseam[1].angle += vseam[1].angle > 0.0f ? -M_PI : M_PI;
1406   vseam[1].normal_cw = !vseam[1].normal_cw;
1407   copy_v2_v2(vseam[1].uv, lt_tri_uv[fidx[1]]);
1408 
1409   for (uint i = 0; i < 2; i++) {
1410     uint vert = ps->mloop_eval[lt->tri[fidx[i]]].v;
1411     ListBase *list = &ps->vertSeams[vert];
1412     VertSeam *item = list->first;
1413 
1414     while (item && item->angle < vseam[i].angle) {
1415       item = item->next;
1416     }
1417 
1418     BLI_insertlinkbefore(list, item, &vseam[i]);
1419   }
1420 }
1421 
1422 /**
1423  * Be tricky with flags, first 4 bits are #PROJ_FACE_SEAM0 to 4,
1424  * last 4 bits are #PROJ_FACE_NOSEAM0 to 4. `1 << i` - where i is `(0..3)`.
1425  *
1426  * If we're multi-threading, make sure threads are locked when this is called.
1427  */
project_face_seams_init(const ProjPaintState * ps,MemArena * arena,const int tri_index,const uint vert_index,bool init_all,const int ibuf_x,const int ibuf_y)1428 static void project_face_seams_init(const ProjPaintState *ps,
1429                                     MemArena *arena,
1430                                     const int tri_index,
1431                                     const uint vert_index,
1432                                     bool init_all,
1433                                     const int ibuf_x,
1434                                     const int ibuf_y)
1435 {
1436   /* vars for the other face, we also set its flag */
1437   int other_face, other_fidx;
1438   /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
1439   int fidx[2] = {2, 0};
1440   const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
1441   LinkNode *node;
1442 
1443   /* initialize face winding if needed */
1444   if ((ps->faceWindingFlags[tri_index] & PROJ_FACE_WINDING_INIT) == 0) {
1445     project_face_winding_init(ps, tri_index);
1446   }
1447 
1448   do {
1449     if (init_all || (ps->mloop_eval[lt->tri[fidx[0]]].v == vert_index) ||
1450         (ps->mloop_eval[lt->tri[fidx[1]]].v == vert_index)) {
1451       if ((ps->faceSeamFlags[tri_index] &
1452            (PROJ_FACE_SEAM0 << fidx[0] | PROJ_FACE_NOSEAM0 << fidx[0])) == 0) {
1453         if (check_seam(ps, tri_index, fidx[0], fidx[1], &other_face, &other_fidx)) {
1454           ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM0 << fidx[0];
1455           insert_seam_vert_array(ps, arena, tri_index, fidx[0], ibuf_x, ibuf_y);
1456 
1457           if (other_face != -1) {
1458             /* Check if the other seam is already set.
1459              * We don't want to insert it in the list twice. */
1460             if ((ps->faceSeamFlags[other_face] & (PROJ_FACE_SEAM0 << other_fidx)) == 0) {
1461               ps->faceSeamFlags[other_face] |= PROJ_FACE_SEAM0 << other_fidx;
1462               insert_seam_vert_array(ps, arena, other_face, other_fidx, ibuf_x, ibuf_y);
1463             }
1464           }
1465         }
1466         else {
1467           ps->faceSeamFlags[tri_index] |= PROJ_FACE_NOSEAM0 << fidx[0];
1468           ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM_INIT0 << fidx[0];
1469 
1470           if (other_face != -1) {
1471             /* second 4 bits for disabled */
1472             ps->faceSeamFlags[other_face] |= PROJ_FACE_NOSEAM0 << other_fidx;
1473             ps->faceSeamFlags[other_face] |= PROJ_FACE_SEAM_INIT0 << other_fidx;
1474           }
1475         }
1476       }
1477     }
1478 
1479     fidx[1] = fidx[0];
1480   } while (fidx[0]--);
1481 
1482   if (init_all) {
1483     char checked_verts = 0;
1484 
1485     fidx[0] = 2;
1486     fidx[1] = 0;
1487 
1488     do {
1489       if ((ps->faceSeamFlags[tri_index] & (PROJ_FACE_SEAM_INIT0 << fidx[0])) == 0) {
1490         for (uint i = 0; i < 2; i++) {
1491           uint vert;
1492 
1493           if ((checked_verts & (1 << fidx[i])) != 0) {
1494             continue;
1495           }
1496 
1497           vert = ps->mloop_eval[lt->tri[fidx[i]]].v;
1498 
1499           for (node = ps->vertFaces[vert]; node; node = node->next) {
1500             const int tri = POINTER_AS_INT(node->link);
1501 
1502             project_face_seams_init(ps, arena, tri, vert, false, ibuf_x, ibuf_y);
1503           }
1504 
1505           checked_verts |= 1 << fidx[i];
1506         }
1507 
1508         ps->faceSeamFlags[tri_index] |= PROJ_FACE_SEAM_INIT0 << fidx[0];
1509       }
1510 
1511       fidx[1] = fidx[0];
1512     } while (fidx[0]--);
1513   }
1514 }
1515 #endif  // PROJ_DEBUG_NOSEAMBLEED
1516 
1517 /* Converts a UV location to a 3D screenspace location
1518  * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
1519  *
1520  * This is used for finding a pixels location in screenspace for painting */
screen_px_from_ortho(const float uv[2],const float v1co[3],const float v2co[3],const float v3co[3],const float uv1co[2],const float uv2co[2],const float uv3co[2],float pixelScreenCo[4],float w[3])1521 static void screen_px_from_ortho(const float uv[2],
1522                                  const float v1co[3],
1523                                  const float v2co[3],
1524                                  const float v3co[3], /* Screenspace coords */
1525                                  const float uv1co[2],
1526                                  const float uv2co[2],
1527                                  const float uv3co[2],
1528                                  float pixelScreenCo[4],
1529                                  float w[3])
1530 {
1531   barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
1532   interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
1533 }
1534 
1535 /* same as screen_px_from_ortho except we
1536  * do perspective correction on the pixel coordinate */
screen_px_from_persp(const float uv[2],const float v1co[4],const float v2co[4],const float v3co[4],const float uv1co[2],const float uv2co[2],const float uv3co[2],float pixelScreenCo[4],float w[3])1537 static void screen_px_from_persp(const float uv[2],
1538                                  const float v1co[4],
1539                                  const float v2co[4],
1540                                  const float v3co[4], /* screenspace coords */
1541                                  const float uv1co[2],
1542                                  const float uv2co[2],
1543                                  const float uv3co[2],
1544                                  float pixelScreenCo[4],
1545                                  float w[3])
1546 {
1547   float w_int[3];
1548   float wtot_inv, wtot;
1549   barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
1550 
1551   /* re-weight from the 4th coord of each screen vert */
1552   w_int[0] = w[0] * v1co[3];
1553   w_int[1] = w[1] * v2co[3];
1554   w_int[2] = w[2] * v3co[3];
1555 
1556   wtot = w_int[0] + w_int[1] + w_int[2];
1557 
1558   if (wtot > 0.0f) {
1559     wtot_inv = 1.0f / wtot;
1560     w_int[0] *= wtot_inv;
1561     w_int[1] *= wtot_inv;
1562     w_int[2] *= wtot_inv;
1563   }
1564   else {
1565     /* Dummy values for zero area face. */
1566     w[0] = w[1] = w[2] = w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
1567   }
1568   /* done re-weighting */
1569 
1570   /* do interpolation based on projected weight */
1571   interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w_int);
1572 }
1573 
1574 /**
1575  * Set a direction vector based on a screen location.
1576  * (use for perspective view, else we can simply use `ps->viewDir`)
1577  *
1578  * Similar functionality to #ED_view3d_win_to_vector
1579  *
1580  * \param r_dir: Resulting direction (length is undefined).
1581  */
screen_px_to_vector_persp(int winx,int winy,const float projmat_inv[4][4],const float view_pos[3],const float co_px[2],float r_dir[3])1582 static void screen_px_to_vector_persp(int winx,
1583                                       int winy,
1584                                       const float projmat_inv[4][4],
1585                                       const float view_pos[3],
1586                                       const float co_px[2],
1587                                       float r_dir[3])
1588 {
1589   r_dir[0] = 2.0f * (co_px[0] / winx) - 1.0f;
1590   r_dir[1] = 2.0f * (co_px[1] / winy) - 1.0f;
1591   r_dir[2] = -0.5f;
1592   mul_project_m4_v3((float(*)[4])projmat_inv, r_dir);
1593   sub_v3_v3(r_dir, view_pos);
1594 }
1595 
1596 /**
1597  * Special function to return the factor to a point along a line in pixel space.
1598  *
1599  * This is needed since we can't use #line_point_factor_v2 for perspective screen-space coords.
1600  *
1601  * \param p: 2D screen-space location.
1602  * \param v1, v2: 3D object-space locations.
1603  */
screen_px_line_point_factor_v2_persp(const ProjPaintState * ps,const float p[2],const float v1[3],const float v2[3])1604 static float screen_px_line_point_factor_v2_persp(const ProjPaintState *ps,
1605                                                   const float p[2],
1606                                                   const float v1[3],
1607                                                   const float v2[3])
1608 {
1609   const float zero[3] = {0};
1610   float v1_proj[3], v2_proj[3];
1611   float dir[3];
1612 
1613   screen_px_to_vector_persp(ps->winx, ps->winy, ps->projectMatInv, ps->viewPos, p, dir);
1614 
1615   sub_v3_v3v3(v1_proj, v1, ps->viewPos);
1616   sub_v3_v3v3(v2_proj, v2, ps->viewPos);
1617 
1618   project_plane_v3_v3v3(v1_proj, v1_proj, dir);
1619   project_plane_v3_v3v3(v2_proj, v2_proj, dir);
1620 
1621   return line_point_factor_v2(zero, v1_proj, v2_proj);
1622 }
1623 
project_face_pixel(const float * lt_tri_uv[3],ImBuf * ibuf_other,const float w[3],uchar rgba_ub[4],float rgba_f[4])1624 static void project_face_pixel(const float *lt_tri_uv[3],
1625                                ImBuf *ibuf_other,
1626                                const float w[3],
1627                                uchar rgba_ub[4],
1628                                float rgba_f[4])
1629 {
1630   float uv_other[2], x, y;
1631 
1632   interp_v2_v2v2v2(uv_other, UNPACK3(lt_tri_uv), w);
1633 
1634   /* use */
1635   uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
1636 
1637   if (ibuf_other->rect_float) { /* from float to float */
1638     bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y);
1639   }
1640   else { /* from char to float */
1641     bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
1642   }
1643 }
1644 
1645 /* run this outside project_paint_uvpixel_init since pixels with mask 0 don't need init */
project_paint_uvpixel_mask(const ProjPaintState * ps,const int tri_index,const float w[3])1646 static float project_paint_uvpixel_mask(const ProjPaintState *ps,
1647                                         const int tri_index,
1648                                         const float w[3])
1649 {
1650   float mask;
1651 
1652   /* Image Mask */
1653   if (ps->do_layer_stencil) {
1654     /* another UV maps image is masking this one's */
1655     ImBuf *ibuf_other;
1656     Image *other_tpage = ps->stencil_ima;
1657 
1658     if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
1659       const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
1660       const float *lt_other_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other)};
1661 
1662       /* BKE_image_acquire_ibuf - TODO - this may be slow */
1663       uchar rgba_ub[4];
1664       float rgba_f[4];
1665 
1666       project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, rgba_f);
1667 
1668       if (ibuf_other->rect_float) { /* from float to float */
1669         mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) * (1.0f / 3.0f)) * rgba_f[3];
1670       }
1671       else { /* from char to float */
1672         mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) * (1.0f / (255.0f * 3.0f))) *
1673                (rgba_ub[3] * (1.0f / 255.0f));
1674       }
1675 
1676       BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
1677 
1678       if (!ps->do_layer_stencil_inv) {
1679         /* matching the gimps layer mask black/white rules, white==full opacity */
1680         mask = (1.0f - mask);
1681       }
1682 
1683       if (mask == 0.0f) {
1684         return 0.0f;
1685       }
1686     }
1687     else {
1688       return 0.0f;
1689     }
1690   }
1691   else {
1692     mask = 1.0f;
1693   }
1694 
1695   if (ps->do_mask_cavity) {
1696     const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
1697     const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
1698     float ca1, ca2, ca3, ca_mask;
1699     ca1 = ps->cavities[lt_vtri[0]];
1700     ca2 = ps->cavities[lt_vtri[1]];
1701     ca3 = ps->cavities[lt_vtri[2]];
1702 
1703     ca_mask = w[0] * ca1 + w[1] * ca2 + w[2] * ca3;
1704     ca_mask = BKE_curvemapping_evaluateF(ps->cavity_curve, 0, ca_mask);
1705     CLAMP(ca_mask, 0.0f, 1.0f);
1706     mask *= ca_mask;
1707   }
1708 
1709   /* calculate mask */
1710   if (ps->do_mask_normal) {
1711     const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
1712     const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
1713     const MPoly *mp = &ps->mpoly_eval[lt->poly];
1714     float no[3], angle_cos;
1715 
1716     if (mp->flag & ME_SMOOTH) {
1717       const short *no1, *no2, *no3;
1718       no1 = ps->mvert_eval[lt_vtri[0]].no;
1719       no2 = ps->mvert_eval[lt_vtri[1]].no;
1720       no3 = ps->mvert_eval[lt_vtri[2]].no;
1721 
1722       no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
1723       no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
1724       no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2];
1725       normalize_v3(no);
1726     }
1727     else {
1728 #if 1
1729       /* In case the normalizing per pixel isn't optimal,
1730        * we could cache or access from evaluated mesh. */
1731       normal_tri_v3(no,
1732                     ps->mvert_eval[lt_vtri[0]].co,
1733                     ps->mvert_eval[lt_vtri[1]].co,
1734                     ps->mvert_eval[lt_vtri[2]].co);
1735 #else
1736       /* don't use because some modifiers dont have normal data (subsurf for eg) */
1737       copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
1738 #endif
1739     }
1740 
1741     if (UNLIKELY(ps->is_flip_object)) {
1742       negate_v3(no);
1743     }
1744 
1745     /* now we can use the normal as a mask */
1746     if (ps->is_ortho) {
1747       angle_cos = dot_v3v3(ps->viewDir, no);
1748     }
1749     else {
1750       /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
1751       float viewDirPersp[3];
1752       const float *co1, *co2, *co3;
1753       co1 = ps->mvert_eval[lt_vtri[0]].co;
1754       co2 = ps->mvert_eval[lt_vtri[1]].co;
1755       co3 = ps->mvert_eval[lt_vtri[2]].co;
1756 
1757       /* Get the direction from the viewPoint to the pixel and normalize */
1758       viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0]));
1759       viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1]));
1760       viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2]));
1761       normalize_v3(viewDirPersp);
1762       if (UNLIKELY(ps->is_flip_object)) {
1763         negate_v3(viewDirPersp);
1764       }
1765 
1766       angle_cos = dot_v3v3(viewDirPersp, no);
1767     }
1768 
1769     /* If backface culling is disabled, allow painting on back faces. */
1770     if (!ps->do_backfacecull) {
1771       angle_cos = fabsf(angle_cos);
1772     }
1773 
1774     if (angle_cos <= ps->normal_angle__cos) {
1775       /* outsize the normal limit*/
1776       return 0.0f;
1777     }
1778     if (angle_cos < ps->normal_angle_inner__cos) {
1779       mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range;
1780     } /* otherwise no mask normal is needed, we're within the limit */
1781   }
1782 
1783   /* This only works when the opacity doesn't change while painting, stylus pressure messes with
1784    * this so don't use it. */
1785   // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush);
1786 
1787   return mask;
1788 }
1789 
project_paint_pixel_sizeof(const short tool)1790 static int project_paint_pixel_sizeof(const short tool)
1791 {
1792   if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) {
1793     return sizeof(ProjPixelClone);
1794   }
1795   return sizeof(ProjPixel);
1796 }
1797 
project_paint_undo_subtiles(const TileInfo * tinf,int tx,int ty)1798 static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
1799 {
1800   ProjPaintImage *pjIma = tinf->pjima;
1801   int tile_index = tx + ty * tinf->tile_width;
1802   bool generate_tile = false;
1803 
1804   /* double check lock to avoid locking */
1805   if (UNLIKELY(!pjIma->undoRect[tile_index])) {
1806     if (tinf->lock) {
1807       BLI_spin_lock(tinf->lock);
1808     }
1809     if (LIKELY(!pjIma->undoRect[tile_index])) {
1810       pjIma->undoRect[tile_index] = TILE_PENDING;
1811       generate_tile = true;
1812     }
1813     if (tinf->lock) {
1814       BLI_spin_unlock(tinf->lock);
1815     }
1816   }
1817 
1818   if (generate_tile) {
1819     ListBase *undo_tiles = ED_image_paint_tile_list_get();
1820     volatile void *undorect;
1821     if (tinf->masked) {
1822       undorect = ED_image_paint_tile_push(undo_tiles,
1823                                           pjIma->ima,
1824                                           pjIma->ibuf,
1825                                           tinf->tmpibuf,
1826                                           &pjIma->iuser,
1827                                           tx,
1828                                           ty,
1829                                           &pjIma->maskRect[tile_index],
1830                                           &pjIma->valid[tile_index],
1831                                           true,
1832                                           false);
1833     }
1834     else {
1835       undorect = ED_image_paint_tile_push(undo_tiles,
1836                                           pjIma->ima,
1837                                           pjIma->ibuf,
1838                                           tinf->tmpibuf,
1839                                           &pjIma->iuser,
1840                                           tx,
1841                                           ty,
1842                                           NULL,
1843                                           &pjIma->valid[tile_index],
1844                                           true,
1845                                           false);
1846     }
1847 
1848     BKE_image_mark_dirty(pjIma->ima, pjIma->ibuf);
1849     /* tile ready, publish */
1850     if (tinf->lock) {
1851       BLI_spin_lock(tinf->lock);
1852     }
1853     pjIma->undoRect[tile_index] = undorect;
1854     if (tinf->lock) {
1855       BLI_spin_unlock(tinf->lock);
1856     }
1857   }
1858 
1859   return tile_index;
1860 }
1861 
1862 /* run this function when we know a bucket's, face's pixel can be initialized,
1863  * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
project_paint_uvpixel_init(const ProjPaintState * ps,MemArena * arena,const TileInfo * tinf,int x_px,int y_px,const float mask,const int tri_index,const float pixelScreenCo[4],const float world_spaceCo[3],const float w[3])1864 static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
1865                                              MemArena *arena,
1866                                              const TileInfo *tinf,
1867                                              int x_px,
1868                                              int y_px,
1869                                              const float mask,
1870                                              const int tri_index,
1871                                              const float pixelScreenCo[4],
1872                                              const float world_spaceCo[3],
1873                                              const float w[3])
1874 {
1875   ProjPixel *projPixel;
1876   int x_tile, y_tile;
1877   int x_round, y_round;
1878   int tile_offset;
1879   /* volatile is important here to ensure pending check is not optimized away by compiler*/
1880   volatile int tile_index;
1881 
1882   ProjPaintImage *projima = tinf->pjima;
1883   ImBuf *ibuf = projima->ibuf;
1884   /* wrap pixel location */
1885 
1886   x_px = mod_i(x_px, ibuf->x);
1887   y_px = mod_i(y_px, ibuf->y);
1888 
1889   BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool));
1890   projPixel = BLI_memarena_alloc(arena, ps->pixel_sizeof);
1891 
1892   /* calculate the undo tile offset of the pixel, used to store the original
1893    * pixel color and accumulated mask if any */
1894   x_tile = x_px >> ED_IMAGE_UNDO_TILE_BITS;
1895   y_tile = y_px >> ED_IMAGE_UNDO_TILE_BITS;
1896 
1897   x_round = x_tile * ED_IMAGE_UNDO_TILE_SIZE;
1898   y_round = y_tile * ED_IMAGE_UNDO_TILE_SIZE;
1899   // memset(projPixel, 0, size);
1900 
1901   tile_offset = (x_px - x_round) + (y_px - y_round) * ED_IMAGE_UNDO_TILE_SIZE;
1902   tile_index = project_paint_undo_subtiles(tinf, x_tile, y_tile);
1903 
1904   /* other thread may be initializing the tile so wait here */
1905   while (projima->undoRect[tile_index] == TILE_PENDING) {
1906     /* pass */
1907   }
1908 
1909   BLI_assert(tile_index <
1910              (ED_IMAGE_UNDO_TILE_NUMBER(ibuf->x) * ED_IMAGE_UNDO_TILE_NUMBER(ibuf->y)));
1911   BLI_assert(tile_offset < (ED_IMAGE_UNDO_TILE_SIZE * ED_IMAGE_UNDO_TILE_SIZE));
1912 
1913   projPixel->valid = projima->valid[tile_index];
1914 
1915   if (ibuf->rect_float) {
1916     projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
1917     projPixel->origColor.f_pt = (float *)projima->undoRect[tile_index] + 4 * tile_offset;
1918     zero_v4(projPixel->newColor.f);
1919   }
1920   else {
1921     projPixel->pixel.ch_pt = (uchar *)(ibuf->rect + (x_px + y_px * ibuf->x));
1922     projPixel->origColor.uint_pt = (uint *)projima->undoRect[tile_index] + tile_offset;
1923     projPixel->newColor.uint = 0;
1924   }
1925 
1926   /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */
1927   if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) {
1928     copy_v3_v3(projPixel->worldCoSS, world_spaceCo);
1929   }
1930 
1931   copy_v2_v2(projPixel->projCoSS, pixelScreenCo);
1932 
1933   projPixel->x_px = x_px;
1934   projPixel->y_px = y_px;
1935 
1936   projPixel->mask = (ushort)(mask * 65535);
1937   if (ps->do_masking) {
1938     projPixel->mask_accum = projima->maskRect[tile_index] + tile_offset;
1939   }
1940   else {
1941     projPixel->mask_accum = NULL;
1942   }
1943 
1944   /* which bounding box cell are we in?, needed for undo */
1945   projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) +
1946                              ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) *
1947                                  PROJ_BOUNDBOX_DIV;
1948 
1949   /* done with view3d_project_float inline */
1950   if (ps->tool == PAINT_TOOL_CLONE) {
1951     if (ps->poly_to_loop_uv_clone) {
1952       ImBuf *ibuf_other;
1953       Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
1954 
1955       if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
1956         const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
1957         const float *lt_other_tri_uv[3] = {
1958             PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other)};
1959 
1960         /* BKE_image_acquire_ibuf - TODO - this may be slow */
1961 
1962         if (ibuf->rect_float) {
1963           if (ibuf_other->rect_float) { /* from float to float */
1964             project_face_pixel(
1965                 lt_other_tri_uv, ibuf_other, w, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
1966           }
1967           else { /* from char to float */
1968             uchar rgba_ub[4];
1969             float rgba[4];
1970             project_face_pixel(lt_other_tri_uv, ibuf_other, w, rgba_ub, NULL);
1971             if (ps->use_colormanagement) {
1972               srgb_to_linearrgb_uchar4(rgba, rgba_ub);
1973             }
1974             else {
1975               rgba_uchar_to_float(rgba, rgba_ub);
1976             }
1977             straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba);
1978           }
1979         }
1980         else {
1981           if (ibuf_other->rect_float) { /* float to char */
1982             float rgba[4];
1983             project_face_pixel(lt_other_tri_uv, ibuf_other, w, NULL, rgba);
1984             premul_to_straight_v4(rgba);
1985             if (ps->use_colormanagement) {
1986               linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
1987             }
1988             else {
1989               rgb_float_to_uchar(((ProjPixelClone *)projPixel)->clonepx.ch, rgba);
1990             }
1991             ((ProjPixelClone *)projPixel)->clonepx.ch[3] = rgba[3] * 255;
1992           }
1993           else { /* char to char */
1994             project_face_pixel(
1995                 lt_other_tri_uv, ibuf_other, w, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
1996           }
1997         }
1998 
1999         BKE_image_release_ibuf(other_tpage, ibuf_other, NULL);
2000       }
2001       else {
2002         if (ibuf->rect_float) {
2003           ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
2004         }
2005         else {
2006           ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
2007         }
2008       }
2009     }
2010     else {
2011       float co[2];
2012       sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset);
2013 
2014       /* no need to initialize the bucket, we're only checking buckets faces and for this
2015        * the faces are already initialized in project_paint_delayed_face_init(...) */
2016       if (ibuf->rect_float) {
2017         if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
2018           /* zero alpha - ignore */
2019           ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
2020         }
2021       }
2022       else {
2023         if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
2024           /* zero alpha - ignore */
2025           ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
2026         }
2027       }
2028     }
2029   }
2030 
2031 #ifdef PROJ_DEBUG_PAINT
2032   if (ibuf->rect_float) {
2033     projPixel->pixel.f_pt[0] = 0;
2034   }
2035   else {
2036     projPixel->pixel.ch_pt[0] = 0;
2037   }
2038 #endif
2039   /* pointer arithmetic */
2040   projPixel->image_index = projima - ps->projImages;
2041 
2042   return projPixel;
2043 }
2044 
line_clip_rect2f(const rctf * cliprect,const rctf * rect,const float l1[2],const float l2[2],float l1_clip[2],float l2_clip[2])2045 static bool line_clip_rect2f(const rctf *cliprect,
2046                              const rctf *rect,
2047                              const float l1[2],
2048                              const float l2[2],
2049                              float l1_clip[2],
2050                              float l2_clip[2])
2051 {
2052   /* first account for horizontal, then vertical lines */
2053   /* horiz */
2054   if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
2055     /* is the line out of range on its Y axis? */
2056     if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
2057       return false;
2058     }
2059     /* line is out of range on its X axis */
2060     if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
2061       return false;
2062     }
2063 
2064     /* this is a single point  (or close to)*/
2065     if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
2066       if (BLI_rctf_isect_pt_v(rect, l1)) {
2067         copy_v2_v2(l1_clip, l1);
2068         copy_v2_v2(l2_clip, l2);
2069         return true;
2070       }
2071       return false;
2072     }
2073 
2074     copy_v2_v2(l1_clip, l1);
2075     copy_v2_v2(l2_clip, l2);
2076     CLAMP(l1_clip[0], rect->xmin, rect->xmax);
2077     CLAMP(l2_clip[0], rect->xmin, rect->xmax);
2078     return true;
2079   }
2080   if (fabsf(l1[0] - l2[0]) < PROJ_PIXEL_TOLERANCE) {
2081     /* is the line out of range on its X axis? */
2082     if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
2083       return false;
2084     }
2085 
2086     /* line is out of range on its Y axis */
2087     if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
2088       return false;
2089     }
2090 
2091     /* this is a single point  (or close to)*/
2092     if (fabsf(l1[1] - l2[1]) < PROJ_PIXEL_TOLERANCE) {
2093       if (BLI_rctf_isect_pt_v(rect, l1)) {
2094         copy_v2_v2(l1_clip, l1);
2095         copy_v2_v2(l2_clip, l2);
2096         return true;
2097       }
2098       return false;
2099     }
2100 
2101     copy_v2_v2(l1_clip, l1);
2102     copy_v2_v2(l2_clip, l2);
2103     CLAMP(l1_clip[1], rect->ymin, rect->ymax);
2104     CLAMP(l2_clip[1], rect->ymin, rect->ymax);
2105     return true;
2106   }
2107 
2108   float isect;
2109   short ok1 = 0;
2110   short ok2 = 0;
2111 
2112   /* Done with vertical lines */
2113 
2114   /* are either of the points inside the rectangle ? */
2115   if (BLI_rctf_isect_pt_v(rect, l1)) {
2116     copy_v2_v2(l1_clip, l1);
2117     ok1 = 1;
2118   }
2119 
2120   if (BLI_rctf_isect_pt_v(rect, l2)) {
2121     copy_v2_v2(l2_clip, l2);
2122     ok2 = 1;
2123   }
2124 
2125   /* line inside rect */
2126   if (ok1 && ok2) {
2127     return true;
2128   }
2129 
2130   /* top/bottom */
2131   if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= cliprect->xmin) &&
2132       (isect <= cliprect->xmax)) {
2133     if (l1[1] < l2[1]) { /* line 1 is outside */
2134       l1_clip[0] = isect;
2135       l1_clip[1] = rect->ymin;
2136       ok1 = 1;
2137     }
2138     else {
2139       l2_clip[0] = isect;
2140       l2_clip[1] = rect->ymin;
2141       ok2 = 2;
2142     }
2143   }
2144 
2145   if (ok1 && ok2) {
2146     return true;
2147   }
2148 
2149   if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= cliprect->xmin) &&
2150       (isect <= cliprect->xmax)) {
2151     if (l1[1] > l2[1]) { /* line 1 is outside */
2152       l1_clip[0] = isect;
2153       l1_clip[1] = rect->ymax;
2154       ok1 = 1;
2155     }
2156     else {
2157       l2_clip[0] = isect;
2158       l2_clip[1] = rect->ymax;
2159       ok2 = 2;
2160     }
2161   }
2162 
2163   if (ok1 && ok2) {
2164     return true;
2165   }
2166 
2167   /* left/right */
2168   if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= cliprect->ymin) &&
2169       (isect <= cliprect->ymax)) {
2170     if (l1[0] < l2[0]) { /* line 1 is outside */
2171       l1_clip[0] = rect->xmin;
2172       l1_clip[1] = isect;
2173       ok1 = 1;
2174     }
2175     else {
2176       l2_clip[0] = rect->xmin;
2177       l2_clip[1] = isect;
2178       ok2 = 2;
2179     }
2180   }
2181 
2182   if (ok1 && ok2) {
2183     return true;
2184   }
2185 
2186   if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= cliprect->ymin) &&
2187       (isect <= cliprect->ymax)) {
2188     if (l1[0] > l2[0]) { /* line 1 is outside */
2189       l1_clip[0] = rect->xmax;
2190       l1_clip[1] = isect;
2191       ok1 = 1;
2192     }
2193     else {
2194       l2_clip[0] = rect->xmax;
2195       l2_clip[1] = isect;
2196       ok2 = 2;
2197     }
2198   }
2199 
2200   if (ok1 && ok2) {
2201     return true;
2202   }
2203   return false;
2204 }
2205 
2206 /**
2207  * Scale the tri about its center
2208  * scaling by #PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on
2209  * the edge of the face but slightly inside it occlusion tests don't return hits on adjacent faces.
2210  */
2211 #ifndef PROJ_DEBUG_NOSEAMBLEED
2212 
scale_tri(float insetCos[3][3],const float * origCos[4],const float inset)2213 static void scale_tri(float insetCos[3][3], const float *origCos[4], const float inset)
2214 {
2215   float cent[3];
2216   cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) * (1.0f / 3.0f);
2217   cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) * (1.0f / 3.0f);
2218   cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) * (1.0f / 3.0f);
2219 
2220   sub_v3_v3v3(insetCos[0], origCos[0], cent);
2221   sub_v3_v3v3(insetCos[1], origCos[1], cent);
2222   sub_v3_v3v3(insetCos[2], origCos[2], cent);
2223 
2224   mul_v3_fl(insetCos[0], inset);
2225   mul_v3_fl(insetCos[1], inset);
2226   mul_v3_fl(insetCos[2], inset);
2227 
2228   add_v3_v3(insetCos[0], cent);
2229   add_v3_v3(insetCos[1], cent);
2230   add_v3_v3(insetCos[2], cent);
2231 }
2232 #endif  // PROJ_DEBUG_NOSEAMBLEED
2233 
len_squared_v2v2_alt(const float v1[2],const float v2_1,const float v2_2)2234 static float len_squared_v2v2_alt(const float v1[2], const float v2_1, const float v2_2)
2235 {
2236   float x, y;
2237 
2238   x = v1[0] - v2_1;
2239   y = v1[1] - v2_2;
2240   return x * x + y * y;
2241 }
2242 
2243 /**
2244  * \note Use a squared value so we can use #len_squared_v2v2
2245  * be sure that you have done a bounds check first or this may fail.
2246  *
2247  * Only give \a bucket_bounds as an arg because we need it elsewhere.
2248  */
project_bucket_isect_circle(const float cent[2],const float radius_squared,const rctf * bucket_bounds)2249 static bool project_bucket_isect_circle(const float cent[2],
2250                                         const float radius_squared,
2251                                         const rctf *bucket_bounds)
2252 {
2253 
2254   /* Would normally to a simple intersection test,
2255    * however we know the bounds of these 2 already intersect so we only need to test
2256    * if the center is inside the vertical or horizontal bounds on either axis,
2257    * this is even less work than an intersection test.
2258    */
2259 #if 0
2260   if (BLI_rctf_isect_pt_v(bucket_bounds, cent)) {
2261     return true;
2262   }
2263 #endif
2264 
2265   if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) ||
2266       (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1])) {
2267     return true;
2268   }
2269 
2270   /* out of bounds left */
2271   if (cent[0] < bucket_bounds->xmin) {
2272     /* lower left out of radius test */
2273     if (cent[1] < bucket_bounds->ymin) {
2274       return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) <
2275               radius_squared) ?
2276                  true :
2277                  false;
2278     }
2279     /* top left test */
2280     if (cent[1] > bucket_bounds->ymax) {
2281       return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) <
2282               radius_squared) ?
2283                  true :
2284                  false;
2285     }
2286   }
2287   else if (cent[0] > bucket_bounds->xmax) {
2288     /* lower right out of radius test */
2289     if (cent[1] < bucket_bounds->ymin) {
2290       return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) <
2291               radius_squared) ?
2292                  true :
2293                  false;
2294     }
2295     /* top right test */
2296     if (cent[1] > bucket_bounds->ymax) {
2297       return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) <
2298               radius_squared) ?
2299                  true :
2300                  false;
2301     }
2302   }
2303 
2304   return false;
2305 }
2306 
2307 /* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
2308  * in ortho view this function gives good results when bucket_bounds are outside the triangle
2309  * however in some cases, perspective view will mess up with faces
2310  * that have minimal screenspace area (viewed from the side).
2311  *
2312  * for this reason its not reliable in this case so we'll use the Simple Barycentric'
2313  * funcs that only account for points inside the triangle.
2314  * however switching back to this for ortho is always an option */
2315 
rect_to_uvspace_ortho(const rctf * bucket_bounds,const float * v1coSS,const float * v2coSS,const float * v3coSS,const float * uv1co,const float * uv2co,const float * uv3co,float bucket_bounds_uv[4][2],const int flip)2316 static void rect_to_uvspace_ortho(const rctf *bucket_bounds,
2317                                   const float *v1coSS,
2318                                   const float *v2coSS,
2319                                   const float *v3coSS,
2320                                   const float *uv1co,
2321                                   const float *uv2co,
2322                                   const float *uv3co,
2323                                   float bucket_bounds_uv[4][2],
2324                                   const int flip)
2325 {
2326   float uv[2];
2327   float w[3];
2328 
2329   /* get the UV space bounding box */
2330   uv[0] = bucket_bounds->xmax;
2331   uv[1] = bucket_bounds->ymin;
2332   barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
2333   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
2334 
2335   // uv[0] = bucket_bounds->xmax; // set above
2336   uv[1] = bucket_bounds->ymax;
2337   barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
2338   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
2339 
2340   uv[0] = bucket_bounds->xmin;
2341   // uv[1] = bucket_bounds->ymax; // set above
2342   barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
2343   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
2344 
2345   // uv[0] = bucket_bounds->xmin; // set above
2346   uv[1] = bucket_bounds->ymin;
2347   barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
2348   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
2349 }
2350 
2351 /* same as above but use barycentric_weights_v2_persp */
rect_to_uvspace_persp(const rctf * bucket_bounds,const float * v1coSS,const float * v2coSS,const float * v3coSS,const float * uv1co,const float * uv2co,const float * uv3co,float bucket_bounds_uv[4][2],const int flip)2352 static void rect_to_uvspace_persp(const rctf *bucket_bounds,
2353                                   const float *v1coSS,
2354                                   const float *v2coSS,
2355                                   const float *v3coSS,
2356                                   const float *uv1co,
2357                                   const float *uv2co,
2358                                   const float *uv3co,
2359                                   float bucket_bounds_uv[4][2],
2360                                   const int flip)
2361 {
2362   float uv[2];
2363   float w[3];
2364 
2365   /* get the UV space bounding box */
2366   uv[0] = bucket_bounds->xmax;
2367   uv[1] = bucket_bounds->ymin;
2368   barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
2369   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w);
2370 
2371   // uv[0] = bucket_bounds->xmax; // set above
2372   uv[1] = bucket_bounds->ymax;
2373   barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
2374   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w);
2375 
2376   uv[0] = bucket_bounds->xmin;
2377   // uv[1] = bucket_bounds->ymax; // set above
2378   barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
2379   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w);
2380 
2381   // uv[0] = bucket_bounds->xmin; // set above
2382   uv[1] = bucket_bounds->ymin;
2383   barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
2384   interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w);
2385 }
2386 
2387 /* This works as we need it to but we can save a few steps and not use it */
2388 
2389 #if 0
2390 static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
2391 {
2392   float v1[2], v2[2];
2393 
2394   v1[0] = p1[0] - p2[0];
2395   v1[1] = p1[1] - p2[1];
2396   v2[0] = p3[0] - p2[0];
2397   v2[1] = p3[1] - p2[1];
2398 
2399   return -atan2f(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]);
2400 }
2401 #endif
2402 
2403 #define ISECT_1 (1)
2404 #define ISECT_2 (1 << 1)
2405 #define ISECT_3 (1 << 2)
2406 #define ISECT_4 (1 << 3)
2407 #define ISECT_ALL3 ((1 << 3) - 1)
2408 #define ISECT_ALL4 ((1 << 4) - 1)
2409 
2410 /* limit must be a fraction over 1.0f */
IsectPT2Df_limit(const float pt[2],const float v1[2],const float v2[2],const float v3[2],const float limit)2411 static bool IsectPT2Df_limit(
2412     const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float limit)
2413 {
2414   return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) /
2415           (area_tri_v2(v1, v2, v3))) < limit;
2416 }
2417 
2418 /* Clip the face by a bucket and set the uv-space bucket_bounds_uv
2419  * so we have the clipped UV's to do pixel intersection tests with
2420  * */
float_z_sort_flip(const void * p1,const void * p2)2421 static int float_z_sort_flip(const void *p1, const void *p2)
2422 {
2423   return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1);
2424 }
2425 
float_z_sort(const void * p1,const void * p2)2426 static int float_z_sort(const void *p1, const void *p2)
2427 {
2428   return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1);
2429 }
2430 
2431 /* assumes one point is within the rectangle */
line_rect_clip(const rctf * rect,const float l1[4],const float l2[4],const float uv1[2],const float uv2[2],float uv[2],bool is_ortho)2432 static bool line_rect_clip(const rctf *rect,
2433                            const float l1[4],
2434                            const float l2[4],
2435                            const float uv1[2],
2436                            const float uv2[2],
2437                            float uv[2],
2438                            bool is_ortho)
2439 {
2440   float min = FLT_MAX, tmp;
2441   float xlen = l2[0] - l1[0];
2442   float ylen = l2[1] - l1[1];
2443 
2444   /* 0.1 might seem too much, but remember, this is pixels! */
2445   if (xlen > 0.1f) {
2446     if ((l1[0] - rect->xmin) * (l2[0] - rect->xmin) <= 0) {
2447       tmp = rect->xmin;
2448       min = min_ff((tmp - l1[0]) / xlen, min);
2449     }
2450     else if ((l1[0] - rect->xmax) * (l2[0] - rect->xmax) < 0) {
2451       tmp = rect->xmax;
2452       min = min_ff((tmp - l1[0]) / xlen, min);
2453     }
2454   }
2455 
2456   if (ylen > 0.1f) {
2457     if ((l1[1] - rect->ymin) * (l2[1] - rect->ymin) <= 0) {
2458       tmp = rect->ymin;
2459       min = min_ff((tmp - l1[1]) / ylen, min);
2460     }
2461     else if ((l1[1] - rect->ymax) * (l2[1] - rect->ymax) < 0) {
2462       tmp = rect->ymax;
2463       min = min_ff((tmp - l1[1]) / ylen, min);
2464     }
2465   }
2466 
2467   if (min == FLT_MAX) {
2468     return false;
2469   }
2470 
2471   tmp = (is_ortho) ? 1.0f : (l1[3] + min * (l2[3] - l1[3]));
2472 
2473   uv[0] = (uv1[0] + min / tmp * (uv2[0] - uv1[0]));
2474   uv[1] = (uv1[1] + min / tmp * (uv2[1] - uv1[1]));
2475 
2476   return true;
2477 }
2478 
project_bucket_clip_face(const bool is_ortho,const bool is_flip_object,const rctf * cliprect,const rctf * bucket_bounds,const float * v1coSS,const float * v2coSS,const float * v3coSS,const float * uv1co,const float * uv2co,const float * uv3co,float bucket_bounds_uv[8][2],int * tot,bool cull)2479 static void project_bucket_clip_face(const bool is_ortho,
2480                                      const bool is_flip_object,
2481                                      const rctf *cliprect,
2482                                      const rctf *bucket_bounds,
2483                                      const float *v1coSS,
2484                                      const float *v2coSS,
2485                                      const float *v3coSS,
2486                                      const float *uv1co,
2487                                      const float *uv2co,
2488                                      const float *uv3co,
2489                                      float bucket_bounds_uv[8][2],
2490                                      int *tot,
2491                                      bool cull)
2492 {
2493   int inside_bucket_flag = 0;
2494   int inside_face_flag = 0;
2495   int flip;
2496   bool collinear = false;
2497 
2498   float bucket_bounds_ss[4][2];
2499 
2500   /* detect pathological case where face the three vertices are almost collinear in screen space.
2501    * mostly those will be culled but when flood filling or with
2502    * smooth shading it's a possibility */
2503   if (min_fff(dist_squared_to_line_v2(v1coSS, v2coSS, v3coSS),
2504               dist_squared_to_line_v2(v2coSS, v3coSS, v1coSS),
2505               dist_squared_to_line_v2(v3coSS, v1coSS, v2coSS)) < PROJ_PIXEL_TOLERANCE) {
2506     collinear = true;
2507   }
2508 
2509   /* get the UV space bounding box */
2510   inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS);
2511   inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1;
2512   inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2;
2513 
2514   if (inside_bucket_flag == ISECT_ALL3) {
2515     /* is_flip_object is used here because we use the face winding */
2516     flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) !=
2517             (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
2518 
2519     /* all screenspace points are inside the bucket bounding box,
2520      * this means we don't need to clip and can simply return the UVs */
2521     if (flip) { /* facing the back? */
2522       copy_v2_v2(bucket_bounds_uv[0], uv3co);
2523       copy_v2_v2(bucket_bounds_uv[1], uv2co);
2524       copy_v2_v2(bucket_bounds_uv[2], uv1co);
2525     }
2526     else {
2527       copy_v2_v2(bucket_bounds_uv[0], uv1co);
2528       copy_v2_v2(bucket_bounds_uv[1], uv2co);
2529       copy_v2_v2(bucket_bounds_uv[2], uv3co);
2530     }
2531 
2532     *tot = 3;
2533     return;
2534   }
2535   /* Handle pathological case here,
2536    * no need for further intersections below since triangle area is almost zero. */
2537   if (collinear) {
2538     int flag;
2539 
2540     (*tot) = 0;
2541 
2542     if (cull) {
2543       return;
2544     }
2545 
2546     if (inside_bucket_flag & ISECT_1) {
2547       copy_v2_v2(bucket_bounds_uv[*tot], uv1co);
2548       (*tot)++;
2549     }
2550 
2551     flag = inside_bucket_flag & (ISECT_1 | ISECT_2);
2552     if (flag && flag != (ISECT_1 | ISECT_2)) {
2553       if (line_rect_clip(
2554               bucket_bounds, v1coSS, v2coSS, uv1co, uv2co, bucket_bounds_uv[*tot], is_ortho)) {
2555         (*tot)++;
2556       }
2557     }
2558 
2559     if (inside_bucket_flag & ISECT_2) {
2560       copy_v2_v2(bucket_bounds_uv[*tot], uv2co);
2561       (*tot)++;
2562     }
2563 
2564     flag = inside_bucket_flag & (ISECT_2 | ISECT_3);
2565     if (flag && flag != (ISECT_2 | ISECT_3)) {
2566       if (line_rect_clip(
2567               bucket_bounds, v2coSS, v3coSS, uv2co, uv3co, bucket_bounds_uv[*tot], is_ortho)) {
2568         (*tot)++;
2569       }
2570     }
2571 
2572     if (inside_bucket_flag & ISECT_3) {
2573       copy_v2_v2(bucket_bounds_uv[*tot], uv3co);
2574       (*tot)++;
2575     }
2576 
2577     flag = inside_bucket_flag & (ISECT_3 | ISECT_1);
2578     if (flag && flag != (ISECT_3 | ISECT_1)) {
2579       if (line_rect_clip(
2580               bucket_bounds, v3coSS, v1coSS, uv3co, uv1co, bucket_bounds_uv[*tot], is_ortho)) {
2581         (*tot)++;
2582       }
2583     }
2584 
2585     if ((*tot) < 3) {
2586       /* no intersections to speak of, but more probable is that all face is just outside the
2587        * rectangle and culled due to float precision issues. Since above tests have failed,
2588        * just dump triangle as is for painting */
2589       *tot = 0;
2590       copy_v2_v2(bucket_bounds_uv[*tot], uv1co);
2591       (*tot)++;
2592       copy_v2_v2(bucket_bounds_uv[*tot], uv2co);
2593       (*tot)++;
2594       copy_v2_v2(bucket_bounds_uv[*tot], uv3co);
2595       (*tot)++;
2596       return;
2597     }
2598 
2599     return;
2600   }
2601 
2602   /* get the UV space bounding box */
2603   /* use IsectPT2Df_limit here so we catch points are are touching the tri edge
2604    * (or a small fraction over) */
2605   bucket_bounds_ss[0][0] = bucket_bounds->xmax;
2606   bucket_bounds_ss[0][1] = bucket_bounds->ymin;
2607   inside_face_flag |= (IsectPT2Df_limit(
2608                            bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
2609                            ISECT_1 :
2610                            0);
2611 
2612   bucket_bounds_ss[1][0] = bucket_bounds->xmax;
2613   bucket_bounds_ss[1][1] = bucket_bounds->ymax;
2614   inside_face_flag |= (IsectPT2Df_limit(
2615                            bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
2616                            ISECT_2 :
2617                            0);
2618 
2619   bucket_bounds_ss[2][0] = bucket_bounds->xmin;
2620   bucket_bounds_ss[2][1] = bucket_bounds->ymax;
2621   inside_face_flag |= (IsectPT2Df_limit(
2622                            bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
2623                            ISECT_3 :
2624                            0);
2625 
2626   bucket_bounds_ss[3][0] = bucket_bounds->xmin;
2627   bucket_bounds_ss[3][1] = bucket_bounds->ymin;
2628   inside_face_flag |= (IsectPT2Df_limit(
2629                            bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ?
2630                            ISECT_4 :
2631                            0);
2632 
2633   flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) !=
2634           (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
2635 
2636   if (inside_face_flag == ISECT_ALL4) {
2637     /* bucket is totally inside the screenspace face, we can safely use weights */
2638 
2639     if (is_ortho) {
2640       rect_to_uvspace_ortho(
2641           bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
2642     }
2643     else {
2644       rect_to_uvspace_persp(
2645           bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
2646     }
2647 
2648     *tot = 4;
2649     return;
2650   }
2651 
2652   {
2653     /* The Complicated Case!
2654      *
2655      * The 2 cases above are where the face is inside the bucket
2656      * or the bucket is inside the face.
2657      *
2658      * we need to make a convex polyline from the intersection between the screenspace face
2659      * and the bucket bounds.
2660      *
2661      * There are a number of ways this could be done, currently it just collects all
2662      * intersecting verts, and line intersections, then sorts them clockwise, this is
2663      * a lot easier than evaluating the geometry to do a correct clipping on both shapes.
2664      */
2665 
2666     /* Add a bunch of points, we know must make up the convex hull
2667      * which is the clipped rect and triangle */
2668 
2669     /* Maximum possible 6 intersections when using a rectangle and triangle */
2670 
2671     /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
2672     float isectVCosSS[8][3];
2673     float v1_clipSS[2], v2_clipSS[2];
2674     float w[3];
2675 
2676     /* calc center */
2677     float cent[2] = {0.0f, 0.0f};
2678     /*float up[2] = {0.0f, 1.0f};*/
2679     bool doubles;
2680 
2681     (*tot) = 0;
2682 
2683     if (inside_face_flag & ISECT_1) {
2684       copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]);
2685       (*tot)++;
2686     }
2687     if (inside_face_flag & ISECT_2) {
2688       copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]);
2689       (*tot)++;
2690     }
2691     if (inside_face_flag & ISECT_3) {
2692       copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]);
2693       (*tot)++;
2694     }
2695     if (inside_face_flag & ISECT_4) {
2696       copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]);
2697       (*tot)++;
2698     }
2699 
2700     if (inside_bucket_flag & ISECT_1) {
2701       copy_v2_v2(isectVCosSS[*tot], v1coSS);
2702       (*tot)++;
2703     }
2704     if (inside_bucket_flag & ISECT_2) {
2705       copy_v2_v2(isectVCosSS[*tot], v2coSS);
2706       (*tot)++;
2707     }
2708     if (inside_bucket_flag & ISECT_3) {
2709       copy_v2_v2(isectVCosSS[*tot], v3coSS);
2710       (*tot)++;
2711     }
2712 
2713     if ((inside_bucket_flag & (ISECT_1 | ISECT_2)) != (ISECT_1 | ISECT_2)) {
2714       if (line_clip_rect2f(cliprect, bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
2715         if ((inside_bucket_flag & ISECT_1) == 0) {
2716           copy_v2_v2(isectVCosSS[*tot], v1_clipSS);
2717           (*tot)++;
2718         }
2719         if ((inside_bucket_flag & ISECT_2) == 0) {
2720           copy_v2_v2(isectVCosSS[*tot], v2_clipSS);
2721           (*tot)++;
2722         }
2723       }
2724     }
2725 
2726     if ((inside_bucket_flag & (ISECT_2 | ISECT_3)) != (ISECT_2 | ISECT_3)) {
2727       if (line_clip_rect2f(cliprect, bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
2728         if ((inside_bucket_flag & ISECT_2) == 0) {
2729           copy_v2_v2(isectVCosSS[*tot], v1_clipSS);
2730           (*tot)++;
2731         }
2732         if ((inside_bucket_flag & ISECT_3) == 0) {
2733           copy_v2_v2(isectVCosSS[*tot], v2_clipSS);
2734           (*tot)++;
2735         }
2736       }
2737     }
2738 
2739     if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) {
2740       if (line_clip_rect2f(cliprect, bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
2741         if ((inside_bucket_flag & ISECT_3) == 0) {
2742           copy_v2_v2(isectVCosSS[*tot], v1_clipSS);
2743           (*tot)++;
2744         }
2745         if ((inside_bucket_flag & ISECT_1) == 0) {
2746           copy_v2_v2(isectVCosSS[*tot], v2_clipSS);
2747           (*tot)++;
2748         }
2749       }
2750     }
2751 
2752     if ((*tot) < 3) { /* no intersections to speak of */
2753       *tot = 0;
2754       return;
2755     }
2756 
2757     /* now we have all points we need, collect their angles and sort them clockwise */
2758 
2759     for (int i = 0; i < (*tot); i++) {
2760       cent[0] += isectVCosSS[i][0];
2761       cent[1] += isectVCosSS[i][1];
2762     }
2763     cent[0] = cent[0] / (float)(*tot);
2764     cent[1] = cent[1] / (float)(*tot);
2765 
2766     /* Collect angles for every point around the center point */
2767 
2768 #if 0 /* uses a few more cycles than the above loop */
2769     for (int i = 0; i < (*tot); i++) {
2770       isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
2771     }
2772 #endif
2773 
2774     /* Abuse this var for the loop below */
2775     v1_clipSS[0] = cent[0];
2776     v1_clipSS[1] = cent[1] + 1.0f;
2777 
2778     for (int i = 0; i < (*tot); i++) {
2779       v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
2780       v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
2781       isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0],
2782                                  v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]);
2783     }
2784 
2785     if (flip) {
2786       qsort(isectVCosSS, *tot, sizeof(float[3]), float_z_sort_flip);
2787     }
2788     else {
2789       qsort(isectVCosSS, *tot, sizeof(float[3]), float_z_sort);
2790     }
2791 
2792     doubles = true;
2793     while (doubles == true) {
2794       doubles = false;
2795 
2796       for (int i = 0; i < (*tot); i++) {
2797         if (fabsf(isectVCosSS[(i + 1) % *tot][0] - isectVCosSS[i][0]) < PROJ_PIXEL_TOLERANCE &&
2798             fabsf(isectVCosSS[(i + 1) % *tot][1] - isectVCosSS[i][1]) < PROJ_PIXEL_TOLERANCE) {
2799           for (int j = i; j < (*tot) - 1; j++) {
2800             isectVCosSS[j][0] = isectVCosSS[j + 1][0];
2801             isectVCosSS[j][1] = isectVCosSS[j + 1][1];
2802           }
2803           /* keep looking for more doubles */
2804           doubles = true;
2805           (*tot)--;
2806         }
2807       }
2808 
2809       /* its possible there is only a few left after remove doubles */
2810       if ((*tot) < 3) {
2811         // printf("removed too many doubles B\n");
2812         *tot = 0;
2813         return;
2814       }
2815     }
2816 
2817     if (is_ortho) {
2818       for (int i = 0; i < (*tot); i++) {
2819         barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
2820         interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
2821       }
2822     }
2823     else {
2824       for (int i = 0; i < (*tot); i++) {
2825         barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
2826         interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
2827       }
2828     }
2829   }
2830 
2831 #ifdef PROJ_DEBUG_PRINT_CLIP
2832   /* include this at the bottom of the above function to debug the output */
2833 
2834   {
2835     /* If there are ever any problems, */
2836     float test_uv[4][2];
2837     int i;
2838     if (is_ortho) {
2839       rect_to_uvspace_ortho(
2840           bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
2841     }
2842     else {
2843       rect_to_uvspace_persp(
2844           bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
2845     }
2846     printf("(  [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ",
2847            test_uv[0][0],
2848            test_uv[0][1],
2849            test_uv[1][0],
2850            test_uv[1][1],
2851            test_uv[2][0],
2852            test_uv[2][1],
2853            test_uv[3][0],
2854            test_uv[3][1]);
2855 
2856     printf("  [(%f,%f), (%f,%f), (%f,%f)], ",
2857            uv1co[0],
2858            uv1co[1],
2859            uv2co[0],
2860            uv2co[1],
2861            uv3co[0],
2862            uv3co[1]);
2863 
2864     printf("[");
2865     for (int i = 0; i < (*tot); i++) {
2866       printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
2867     }
2868     printf("]),\\\n");
2869   }
2870 #endif
2871 }
2872 
2873 /*
2874  * # This script creates faces in a blender scene from printed data above.
2875  *
2876  * project_ls = [
2877  * ...(output from above block)...
2878  * ]
2879  *
2880  * from Blender import Scene, Mesh, Window, sys, Mathutils
2881  *
2882  * import bpy
2883  *
2884  * V = Mathutils.Vector
2885  *
2886  * def main():
2887  *     sce = bpy.data.scenes.active
2888  *
2889  *     for item in project_ls:
2890  *         bb = item[0]
2891  *         uv = item[1]
2892  *         poly = item[2]
2893  *
2894  *         me = bpy.data.meshes.new()
2895  *         ob = sce.objects.new(me)
2896  *
2897  *         me.verts.extend([V(bb[0]).xyz, V(bb[1]).xyz, V(bb[2]).xyz, V(bb[3]).xyz])
2898  *         me.faces.extend([(0,1,2,3),])
2899  *         me.verts.extend([V(uv[0]).xyz, V(uv[1]).xyz, V(uv[2]).xyz])
2900  *         me.faces.extend([(4,5,6),])
2901  *
2902  *         vs = [V(p).xyz for p in poly]
2903  *         print len(vs)
2904  *         l = len(me.verts)
2905  *         me.verts.extend(vs)
2906  *
2907  *         i = l
2908  *         while i < len(me.verts):
2909  *             ii = i + 1
2910  *             if ii == len(me.verts):
2911  *                 ii = l
2912  *             me.edges.extend([i, ii])
2913  *             i += 1
2914  *
2915  * if __name__ == '__main__':
2916  *     main()
2917  */
2918 
2919 #undef ISECT_1
2920 #undef ISECT_2
2921 #undef ISECT_3
2922 #undef ISECT_4
2923 #undef ISECT_ALL3
2924 #undef ISECT_ALL4
2925 
2926 /* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
2927  * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */
IsectPoly2Df(const float pt[2],const float uv[][2],const int tot)2928 static bool IsectPoly2Df(const float pt[2], const float uv[][2], const int tot)
2929 {
2930   int i;
2931   if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f) {
2932     return false;
2933   }
2934 
2935   for (i = 1; i < tot; i++) {
2936     if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f) {
2937       return false;
2938     }
2939   }
2940 
2941   return true;
2942 }
IsectPoly2Df_twoside(const float pt[2],const float uv[][2],const int tot)2943 static bool IsectPoly2Df_twoside(const float pt[2], const float uv[][2], const int tot)
2944 {
2945   const bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f);
2946 
2947   for (int i = 1; i < tot; i++) {
2948     if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side) {
2949       return false;
2950     }
2951   }
2952 
2953   return true;
2954 }
2955 
2956 /* One of the most important function for projection painting,
2957  * since it selects the pixels to be added into each bucket.
2958  *
2959  * initialize pixels from this face where it intersects with the bucket_index,
2960  * optionally initialize pixels for removing seams */
project_paint_face_init(const ProjPaintState * ps,const int thread_index,const int bucket_index,const int tri_index,const int image_index,const rctf * clip_rect,const rctf * bucket_bounds,ImBuf * ibuf,ImBuf ** tmpibuf)2961 static void project_paint_face_init(const ProjPaintState *ps,
2962                                     const int thread_index,
2963                                     const int bucket_index,
2964                                     const int tri_index,
2965                                     const int image_index,
2966                                     const rctf *clip_rect,
2967                                     const rctf *bucket_bounds,
2968                                     ImBuf *ibuf,
2969                                     ImBuf **tmpibuf)
2970 {
2971   /* Projection vars, to get the 3D locations into screen space  */
2972   MemArena *arena = ps->arena_mt[thread_index];
2973   LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
2974   LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
2975   bool threaded = (ps->thread_tot > 1);
2976 
2977   TileInfo tinf = {
2978       ps->tile_lock,
2979       ps->do_masking,
2980       ED_IMAGE_UNDO_TILE_NUMBER(ibuf->x),
2981       tmpibuf,
2982       ps->projImages + image_index,
2983   };
2984 
2985   const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
2986   const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
2987   const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
2988 
2989   /* UV/pixel seeking data */
2990   /* Image X/Y-Pixel */
2991   int x, y;
2992   float mask;
2993   /* Image floating point UV - same as x, y but from 0.0-1.0 */
2994   float uv[2];
2995 
2996   /* vert co screen-space, these will be assigned to lt_vtri[0-2] */
2997   const float *v1coSS, *v2coSS, *v3coSS;
2998 
2999   /* vertex screenspace coords */
3000   const float *vCo[3];
3001 
3002   float w[3], wco[3];
3003 
3004   /* for convenience only, these will be assigned to lt_tri_uv[0],1,2 or lt_tri_uv[0],2,3 */
3005   float *uv1co, *uv2co, *uv3co;
3006   float pixelScreenCo[4];
3007   bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D;
3008 
3009   /* ispace bounds */
3010   rcti bounds_px;
3011   /* vars for getting uvspace bounds */
3012 
3013   /* bucket bounds in UV space so we can init pixels only for this face,  */
3014   float lt_uv_pxoffset[3][2];
3015   float xhalfpx, yhalfpx;
3016   const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y;
3017 
3018   /* for early loop exit */
3019   int has_x_isect = 0, has_isect = 0;
3020 
3021   float uv_clip[8][2];
3022   int uv_clip_tot;
3023   const bool is_ortho = ps->is_ortho;
3024   const bool is_flip_object = ps->is_flip_object;
3025   const bool do_backfacecull = ps->do_backfacecull;
3026   const bool do_clip = RV3D_CLIPPING_ENABLED(ps->v3d, ps->rv3d);
3027 
3028   vCo[0] = ps->mvert_eval[lt_vtri[0]].co;
3029   vCo[1] = ps->mvert_eval[lt_vtri[1]].co;
3030   vCo[2] = ps->mvert_eval[lt_vtri[2]].co;
3031 
3032   /* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel
3033    * this is done so we can avoid offsetting all the pixels by 0.5 which causes
3034    * problems when wrapping negative coords */
3035   xhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 3.0f))) / ibuf_xf;
3036   yhalfpx = (0.5f + (PROJ_PIXEL_TOLERANCE * (1.0f / 4.0f))) / ibuf_yf;
3037 
3038   /* Note about (PROJ_GEOM_TOLERANCE/x) above...
3039    * Needed to add this offset since UV coords are often quads aligned to pixels.
3040    * In this case pixels can be exactly between 2 triangles causing nasty
3041    * artifacts.
3042    *
3043    * This workaround can be removed and painting will still work on most cases
3044    * but since the first thing most people try is painting onto a quad- better make it work.
3045    */
3046 
3047   lt_uv_pxoffset[0][0] = lt_tri_uv[0][0] - xhalfpx;
3048   lt_uv_pxoffset[0][1] = lt_tri_uv[0][1] - yhalfpx;
3049 
3050   lt_uv_pxoffset[1][0] = lt_tri_uv[1][0] - xhalfpx;
3051   lt_uv_pxoffset[1][1] = lt_tri_uv[1][1] - yhalfpx;
3052 
3053   lt_uv_pxoffset[2][0] = lt_tri_uv[2][0] - xhalfpx;
3054   lt_uv_pxoffset[2][1] = lt_tri_uv[2][1] - yhalfpx;
3055 
3056   {
3057     uv1co = lt_uv_pxoffset[0]; /* was lt_tri_uv[i1]; */
3058     uv2co = lt_uv_pxoffset[1]; /* was lt_tri_uv[i2]; */
3059     uv3co = lt_uv_pxoffset[2]; /* was lt_tri_uv[i3]; */
3060 
3061     v1coSS = ps->screenCoords[lt_vtri[0]];
3062     v2coSS = ps->screenCoords[lt_vtri[1]];
3063     v3coSS = ps->screenCoords[lt_vtri[2]];
3064 
3065     /* This function gives is a concave polyline in UV space from the clipped tri*/
3066     project_bucket_clip_face(is_ortho,
3067                              is_flip_object,
3068                              clip_rect,
3069                              bucket_bounds,
3070                              v1coSS,
3071                              v2coSS,
3072                              v3coSS,
3073                              uv1co,
3074                              uv2co,
3075                              uv3co,
3076                              uv_clip,
3077                              &uv_clip_tot,
3078                              do_backfacecull || ps->do_occlude);
3079 
3080     /* Sometimes this happens, better just allow for 8 intersections
3081      * even though there should be max 6 */
3082 #if 0
3083     if (uv_clip_tot > 6) {
3084       printf("this should never happen! %d\n", uv_clip_tot);
3085     }
3086 #endif
3087 
3088     if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
3089 #if 0
3090       project_paint_undo_tiles_init(
3091           &bounds_px, ps->projImages + image_index, tmpibuf, tile_width, threaded, ps->do_masking);
3092 #endif
3093       /* clip face and */
3094 
3095       has_isect = 0;
3096       for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
3097         // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
3098         /* use pixel offset UV coords instead */
3099         uv[1] = (float)y / ibuf_yf;
3100 
3101         has_x_isect = 0;
3102         for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
3103           // uv[0] = (((float)x) + 0.5f) / ibuf->x;
3104           /* use pixel offset UV coords instead */
3105           uv[0] = (float)x / ibuf_xf;
3106 
3107           /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesn't work,
3108            * could check the poly direction but better to do this */
3109           if ((do_backfacecull == true && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
3110               (do_backfacecull == false && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) {
3111 
3112             has_x_isect = has_isect = 1;
3113 
3114             if (is_ortho) {
3115               screen_px_from_ortho(
3116                   uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
3117             }
3118             else {
3119               screen_px_from_persp(
3120                   uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
3121             }
3122 
3123             /* a pity we need to get the worldspace pixel location here */
3124             if (do_clip || do_3d_mapping) {
3125               interp_v3_v3v3v3(wco,
3126                                ps->mvert_eval[lt_vtri[0]].co,
3127                                ps->mvert_eval[lt_vtri[1]].co,
3128                                ps->mvert_eval[lt_vtri[2]].co,
3129                                w);
3130               if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
3131                 /* Watch out that no code below this needs to run */
3132                 continue;
3133               }
3134             }
3135 
3136             /* Is this UV visible from the view? - raytrace */
3137             /* project_paint_PickFace is less complex, use for testing */
3138             // if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == tri_index) {
3139             if ((ps->do_occlude == false) ||
3140                 !project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo)) {
3141               mask = project_paint_uvpixel_mask(ps, tri_index, w);
3142 
3143               if (mask > 0.0f) {
3144                 BLI_linklist_prepend_arena(
3145                     bucketPixelNodes,
3146                     project_paint_uvpixel_init(
3147                         ps, arena, &tinf, x, y, mask, tri_index, pixelScreenCo, wco, w),
3148                     arena);
3149               }
3150             }
3151           }
3152           //#if 0
3153           else if (has_x_isect) {
3154             /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
3155             break;
3156           }
3157           //#endif
3158         }
3159 
3160 #if 0 /* TODO - investigate why this doesn't work sometimes! it should! */
3161         /* no intersection for this entire row,
3162          * after some intersection above means we can quit now */
3163         if (has_x_isect == 0 && has_isect) {
3164           break;
3165         }
3166 #endif
3167       }
3168     }
3169   }
3170 
3171 #ifndef PROJ_DEBUG_NOSEAMBLEED
3172   if (ps->seam_bleed_px > 0.0f && !(ps->faceSeamFlags[tri_index] & PROJ_FACE_DEGENERATE)) {
3173     int face_seam_flag;
3174 
3175     if (threaded) {
3176       /* Other threads could be modifying these vars. */
3177       BLI_thread_lock(LOCK_CUSTOM1);
3178     }
3179 
3180     face_seam_flag = ps->faceSeamFlags[tri_index];
3181 
3182     /* are any of our edges un-initialized? */
3183     if ((face_seam_flag & PROJ_FACE_SEAM_INIT0) == 0 ||
3184         (face_seam_flag & PROJ_FACE_SEAM_INIT1) == 0 ||
3185         (face_seam_flag & PROJ_FACE_SEAM_INIT2) == 0) {
3186       project_face_seams_init(ps, arena, tri_index, 0, true, ibuf->x, ibuf->y);
3187       face_seam_flag = ps->faceSeamFlags[tri_index];
3188 #  if 0
3189       printf("seams - %d %d %d %d\n",
3190              flag & PROJ_FACE_SEAM0,
3191              flag & PROJ_FACE_SEAM1,
3192              flag & PROJ_FACE_SEAM2);
3193 #  endif
3194     }
3195 
3196     if ((face_seam_flag & (PROJ_FACE_SEAM0 | PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2)) == 0) {
3197 
3198       if (threaded) {
3199         /* Other threads could be modifying these vars. */
3200         BLI_thread_unlock(LOCK_CUSTOM1);
3201       }
3202     }
3203     else {
3204       /* we have a seam - deal with it! */
3205 
3206       /* inset face coords.  NOTE!!! ScreenSace for ortho, Worldspace in perspective view */
3207       float insetCos[3][3];
3208 
3209       /* vertex screenspace coords */
3210       const float *vCoSS[3];
3211 
3212       /* Store the screenspace coords of the face,
3213        * clipped by the bucket's screen aligned rectangle. */
3214       float bucket_clip_edges[2][2];
3215       float edge_verts_inset_clip[2][3];
3216       /* face edge pairs - loop through these:
3217        * ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
3218       int fidx1, fidx2;
3219 
3220       float seam_subsection[4][2];
3221       float fac1, fac2;
3222 
3223       /* Pixelspace UVs. */
3224       float lt_puv[3][2];
3225 
3226       lt_puv[0][0] = lt_uv_pxoffset[0][0] * ibuf->x;
3227       lt_puv[0][1] = lt_uv_pxoffset[0][1] * ibuf->y;
3228 
3229       lt_puv[1][0] = lt_uv_pxoffset[1][0] * ibuf->x;
3230       lt_puv[1][1] = lt_uv_pxoffset[1][1] * ibuf->y;
3231 
3232       lt_puv[2][0] = lt_uv_pxoffset[2][0] * ibuf->x;
3233       lt_puv[2][1] = lt_uv_pxoffset[2][1] * ibuf->y;
3234 
3235       if ((ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM0) ||
3236           (ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM1) ||
3237           (ps->faceSeamFlags[tri_index] & PROJ_FACE_SEAM2)) {
3238         uv_image_outset(ps, lt_uv_pxoffset, lt_puv, tri_index, ibuf->x, ibuf->y);
3239       }
3240 
3241       /* ps->loopSeamUVs cant be modified when threading, now this is done we can unlock. */
3242       if (threaded) {
3243         /* Other threads could be modifying these vars */
3244         BLI_thread_unlock(LOCK_CUSTOM1);
3245       }
3246 
3247       vCoSS[0] = ps->screenCoords[lt_vtri[0]];
3248       vCoSS[1] = ps->screenCoords[lt_vtri[1]];
3249       vCoSS[2] = ps->screenCoords[lt_vtri[2]];
3250 
3251       /* PROJ_FACE_SCALE_SEAM must be slightly less than 1.0f */
3252       if (is_ortho) {
3253         scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
3254       }
3255       else {
3256         scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
3257       }
3258 
3259       for (fidx1 = 0; fidx1 < 3; fidx1++) {
3260         /* next fidx in the face (0,1,2) -> (1,2,0) */
3261         fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1;
3262 
3263         if ((face_seam_flag & (1 << fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
3264             line_clip_rect2f(clip_rect,
3265                              bucket_bounds,
3266                              vCoSS[fidx1],
3267                              vCoSS[fidx2],
3268                              bucket_clip_edges[0],
3269                              bucket_clip_edges[1])) {
3270           /* Avoid div by zero. */
3271           if (len_squared_v2v2(vCoSS[fidx1], vCoSS[fidx2]) > FLT_EPSILON) {
3272             uint loop_idx = ps->mlooptri_eval[tri_index].tri[fidx1];
3273             LoopSeamData *seam_data = &ps->loopSeamData[loop_idx];
3274             float(*seam_uvs)[2] = seam_data->seam_uvs;
3275 
3276             if (is_ortho) {
3277               fac1 = line_point_factor_v2(bucket_clip_edges[0], vCoSS[fidx1], vCoSS[fidx2]);
3278               fac2 = line_point_factor_v2(bucket_clip_edges[1], vCoSS[fidx1], vCoSS[fidx2]);
3279             }
3280             else {
3281               fac1 = screen_px_line_point_factor_v2_persp(
3282                   ps, bucket_clip_edges[0], vCo[fidx1], vCo[fidx2]);
3283               fac2 = screen_px_line_point_factor_v2_persp(
3284                   ps, bucket_clip_edges[1], vCo[fidx1], vCo[fidx2]);
3285             }
3286 
3287             interp_v2_v2v2(seam_subsection[0], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac1);
3288             interp_v2_v2v2(seam_subsection[1], lt_uv_pxoffset[fidx1], lt_uv_pxoffset[fidx2], fac2);
3289 
3290             interp_v2_v2v2(seam_subsection[2], seam_uvs[0], seam_uvs[1], fac2);
3291             interp_v2_v2v2(seam_subsection[3], seam_uvs[0], seam_uvs[1], fac1);
3292 
3293             /* if the bucket_clip_edges values Z values was kept we could avoid this
3294              * Inset needs to be added so occlusion tests wont hit adjacent faces */
3295             interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
3296             interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
3297 
3298             if (pixel_bounds_uv(seam_subsection, &bounds_px, ibuf->x, ibuf->y)) {
3299               /* bounds between the seam rect and the uvspace bucket pixels */
3300 
3301               has_isect = 0;
3302               for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
3303                 // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
3304                 /* use offset uvs instead */
3305                 uv[1] = (float)y / ibuf_yf;
3306 
3307                 has_x_isect = 0;
3308                 for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
3309                   const float puv[2] = {(float)x, (float)y};
3310                   bool in_bounds;
3311                   // uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
3312                   /* use offset uvs instead */
3313                   uv[0] = (float)x / ibuf_xf;
3314 
3315                   /* test we're inside uvspace bucket and triangle bounds */
3316                   if (equals_v2v2(seam_uvs[0], seam_uvs[1])) {
3317                     in_bounds = isect_point_tri_v2(uv, UNPACK3(seam_subsection));
3318                   }
3319                   else {
3320                     in_bounds = isect_point_quad_v2(uv, UNPACK4(seam_subsection));
3321                   }
3322 
3323                   if (in_bounds) {
3324                     if ((seam_data->corner_dist_sq[0] > 0.0f) &&
3325                         (len_squared_v2v2(puv, seam_data->seam_puvs[0]) <
3326                          seam_data->corner_dist_sq[0]) &&
3327                         (len_squared_v2v2(puv, lt_puv[fidx1]) > ps->seam_bleed_px_sq)) {
3328                       in_bounds = false;
3329                     }
3330                     else if ((seam_data->corner_dist_sq[1] > 0.0f) &&
3331                              (len_squared_v2v2(puv, seam_data->seam_puvs[1]) <
3332                               seam_data->corner_dist_sq[1]) &&
3333                              (len_squared_v2v2(puv, lt_puv[fidx2]) > ps->seam_bleed_px_sq)) {
3334                       in_bounds = false;
3335                     }
3336                   }
3337 
3338                   if (in_bounds) {
3339                     float pixel_on_edge[4];
3340                     float fac;
3341 
3342                     if (is_ortho) {
3343                       screen_px_from_ortho(
3344                           uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
3345                     }
3346                     else {
3347                       screen_px_from_persp(
3348                           uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
3349                     }
3350 
3351                     /* We need the coord of the pixel on the edge, for the occlusion query. */
3352                     fac = resolve_quad_u_v2(uv, UNPACK4(seam_subsection));
3353                     interp_v3_v3v3(
3354                         pixel_on_edge, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac);
3355 
3356                     if (!is_ortho) {
3357                       pixel_on_edge[3] = 1.0f;
3358                       /* cast because of const */
3359                       mul_m4_v4((float(*)[4])ps->projectMat, pixel_on_edge);
3360                       pixel_on_edge[0] = (float)(ps->winx * 0.5f) +
3361                                          (ps->winx * 0.5f) * pixel_on_edge[0] / pixel_on_edge[3];
3362                       pixel_on_edge[1] = (float)(ps->winy * 0.5f) +
3363                                          (ps->winy * 0.5f) * pixel_on_edge[1] / pixel_on_edge[3];
3364                       /* Use the depth for bucket point occlusion */
3365                       pixel_on_edge[2] = pixel_on_edge[2] / pixel_on_edge[3];
3366                     }
3367 
3368                     if ((ps->do_occlude == false) ||
3369                         !project_bucket_point_occluded(
3370                             ps, bucketFaceNodes, tri_index, pixel_on_edge)) {
3371                       /* a pity we need to get the worldspace
3372                        * pixel location here */
3373                       if (do_clip || do_3d_mapping) {
3374                         interp_v3_v3v3v3(wco, vCo[0], vCo[1], vCo[2], w);
3375 
3376                         if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
3377                           /* Watch out that no code below
3378                            * this needs to run */
3379                           continue;
3380                         }
3381                       }
3382 
3383                       mask = project_paint_uvpixel_mask(ps, tri_index, w);
3384 
3385                       if (mask > 0.0f) {
3386                         BLI_linklist_prepend_arena(
3387                             bucketPixelNodes,
3388                             project_paint_uvpixel_init(
3389                                 ps, arena, &tinf, x, y, mask, tri_index, pixelScreenCo, wco, w),
3390                             arena);
3391                       }
3392                     }
3393                   }
3394                   else if (has_x_isect) {
3395                     /* assuming the face is not a bow-tie - we know
3396                      * we can't intersect again on the X */
3397                     break;
3398                   }
3399                 }
3400 
3401 #  if 0 /* TODO - investigate why this doesn't work sometimes! it should! */
3402                 /* no intersection for this entire row,
3403                  * after some intersection above means we can quit now */
3404                 if (has_x_isect == 0 && has_isect) {
3405                   break;
3406                 }
3407 #  endif
3408               }
3409             }
3410           }
3411         }
3412       }
3413     }
3414   }
3415 #else
3416   UNUSED_VARS(vCo, threaded);
3417 #endif /* PROJ_DEBUG_NOSEAMBLEED */
3418 }
3419 
3420 /**
3421  * Takes floating point screenspace min/max and
3422  * returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags
3423  */
project_paint_bucket_bounds(const ProjPaintState * ps,const float min[2],const float max[2],int bucketMin[2],int bucketMax[2])3424 static void project_paint_bucket_bounds(const ProjPaintState *ps,
3425                                         const float min[2],
3426                                         const float max[2],
3427                                         int bucketMin[2],
3428                                         int bucketMax[2])
3429 {
3430   /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
3431 
3432   /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f
3433    * is always truncated to 1, is this really correct?? - jwilkins */
3434 
3435   /* these offsets of 0.5 and 1.5 seem odd but they are correct */
3436   bucketMin[0] =
3437       (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f);
3438   bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) *
3439                              ps->buckets_y) +
3440                        0.5f);
3441 
3442   bucketMax[0] =
3443       (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
3444   bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) *
3445                              ps->buckets_y) +
3446                        1.5f);
3447 
3448   /* in case the rect is outside the mesh 2d bounds */
3449   CLAMP(bucketMin[0], 0, ps->buckets_x);
3450   CLAMP(bucketMin[1], 0, ps->buckets_y);
3451 
3452   CLAMP(bucketMax[0], 0, ps->buckets_x);
3453   CLAMP(bucketMax[1], 0, ps->buckets_y);
3454 }
3455 
3456 /* set bucket_bounds to a screen space-aligned floating point bound-box */
project_bucket_bounds(const ProjPaintState * ps,const int bucket_x,const int bucket_y,rctf * bucket_bounds)3457 static void project_bucket_bounds(const ProjPaintState *ps,
3458                                   const int bucket_x,
3459                                   const int bucket_y,
3460                                   rctf *bucket_bounds)
3461 {
3462   /* left */
3463   bucket_bounds->xmin = (ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)));
3464   /* right */
3465   bucket_bounds->xmax = (ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)));
3466 
3467   /* bottom */
3468   bucket_bounds->ymin = (ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)));
3469   /* top */
3470   bucket_bounds->ymax = (ps->screenMin[1] +
3471                          ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)));
3472 }
3473 
3474 /* Fill this bucket with pixels from the faces that intersect it.
3475  *
3476  * have bucket_bounds as an argument so we don't need to give bucket_x/y the rect function needs */
project_bucket_init(const ProjPaintState * ps,const int thread_index,const int bucket_index,const rctf * clip_rect,const rctf * bucket_bounds)3477 static void project_bucket_init(const ProjPaintState *ps,
3478                                 const int thread_index,
3479                                 const int bucket_index,
3480                                 const rctf *clip_rect,
3481                                 const rctf *bucket_bounds)
3482 {
3483   LinkNode *node;
3484   int tri_index, image_index = 0;
3485   ImBuf *ibuf = NULL;
3486   Image *tpage_last = NULL, *tpage;
3487   ImBuf *tmpibuf = NULL;
3488   int tile_last = 0;
3489 
3490   if (ps->image_tot == 1) {
3491     /* Simple loop, no context switching */
3492     ibuf = ps->projImages[0].ibuf;
3493 
3494     for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
3495       project_paint_face_init(ps,
3496                               thread_index,
3497                               bucket_index,
3498                               POINTER_AS_INT(node->link),
3499                               0,
3500                               clip_rect,
3501                               bucket_bounds,
3502                               ibuf,
3503                               &tmpibuf);
3504     }
3505   }
3506   else {
3507 
3508     /* More complicated loop, switch between images */
3509     for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
3510       tri_index = POINTER_AS_INT(node->link);
3511 
3512       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
3513       const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
3514 
3515       /* Image context switching */
3516       tpage = project_paint_face_paint_image(ps, tri_index);
3517       int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
3518       if (tpage_last != tpage || tile_last != tile) {
3519         tpage_last = tpage;
3520         tile_last = tile;
3521 
3522         ibuf = NULL;
3523         for (image_index = 0; image_index < ps->image_tot; image_index++) {
3524           ProjPaintImage *projIma = &ps->projImages[image_index];
3525           if ((projIma->ima == tpage) && (projIma->iuser.tile == tile)) {
3526             ibuf = projIma->ibuf;
3527             break;
3528           }
3529         }
3530         BLI_assert(ibuf != NULL);
3531       }
3532       /* context switching done */
3533 
3534       project_paint_face_init(ps,
3535                               thread_index,
3536                               bucket_index,
3537                               tri_index,
3538                               image_index,
3539                               clip_rect,
3540                               bucket_bounds,
3541                               ibuf,
3542                               &tmpibuf);
3543     }
3544   }
3545 
3546   if (tmpibuf) {
3547     IMB_freeImBuf(tmpibuf);
3548   }
3549 
3550   ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
3551 }
3552 
3553 /* We want to know if a bucket and a face overlap in screen-space
3554  *
3555  * Note, if this ever returns false positives its not that bad, since a face in the bounding area
3556  * will have its pixels calculated when it might not be needed later, (at the moment at least)
3557  * obviously it shouldn't have bugs though */
3558 
project_bucket_face_isect(ProjPaintState * ps,int bucket_x,int bucket_y,const MLoopTri * lt)3559 static bool project_bucket_face_isect(ProjPaintState *ps,
3560                                       int bucket_x,
3561                                       int bucket_y,
3562                                       const MLoopTri *lt)
3563 {
3564   /* TODO - replace this with a trickier method that uses side-of-line for all
3565    * #ProjPaintState.screenCoords edges against the closest bucket corner. */
3566   const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
3567   rctf bucket_bounds;
3568   float p1[2], p2[2], p3[2], p4[2];
3569   const float *v, *v1, *v2, *v3;
3570   int fidx;
3571 
3572   project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
3573 
3574   /* Is one of the faces verts in the bucket bounds? */
3575 
3576   fidx = 2;
3577   do {
3578     v = ps->screenCoords[lt_vtri[fidx]];
3579     if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) {
3580       return true;
3581     }
3582   } while (fidx--);
3583 
3584   v1 = ps->screenCoords[lt_vtri[0]];
3585   v2 = ps->screenCoords[lt_vtri[1]];
3586   v3 = ps->screenCoords[lt_vtri[2]];
3587 
3588   p1[0] = bucket_bounds.xmin;
3589   p1[1] = bucket_bounds.ymin;
3590   p2[0] = bucket_bounds.xmin;
3591   p2[1] = bucket_bounds.ymax;
3592   p3[0] = bucket_bounds.xmax;
3593   p3[1] = bucket_bounds.ymax;
3594   p4[0] = bucket_bounds.xmax;
3595   p4[1] = bucket_bounds.ymin;
3596 
3597   if (isect_point_tri_v2(p1, v1, v2, v3) || isect_point_tri_v2(p2, v1, v2, v3) ||
3598       isect_point_tri_v2(p3, v1, v2, v3) || isect_point_tri_v2(p4, v1, v2, v3) ||
3599       /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
3600       (isect_seg_seg_v2(p1, p2, v1, v2) || isect_seg_seg_v2(p1, p2, v2, v3)) ||
3601       (isect_seg_seg_v2(p2, p3, v1, v2) || isect_seg_seg_v2(p2, p3, v2, v3)) ||
3602       (isect_seg_seg_v2(p3, p4, v1, v2) || isect_seg_seg_v2(p3, p4, v2, v3)) ||
3603       (isect_seg_seg_v2(p4, p1, v1, v2) || isect_seg_seg_v2(p4, p1, v2, v3))) {
3604     return true;
3605   }
3606 
3607   return false;
3608 }
3609 
3610 /* Add faces to the bucket but don't initialize its pixels
3611  * TODO - when painting occluded, sort the faces on their min-Z
3612  * and only add faces that faces that are not occluded */
project_paint_delayed_face_init(ProjPaintState * ps,const MLoopTri * lt,const int tri_index)3613 static void project_paint_delayed_face_init(ProjPaintState *ps,
3614                                             const MLoopTri *lt,
3615                                             const int tri_index)
3616 {
3617   const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
3618   float min[2], max[2], *vCoSS;
3619   /* for ps->bucketRect indexing */
3620   int bucketMin[2], bucketMax[2];
3621   int fidx, bucket_x, bucket_y;
3622   /* for early loop exit */
3623   int has_x_isect = -1, has_isect = 0;
3624   /* just use the first thread arena since threading has not started yet */
3625   MemArena *arena = ps->arena_mt[0];
3626 
3627   INIT_MINMAX2(min, max);
3628 
3629   fidx = 2;
3630   do {
3631     vCoSS = ps->screenCoords[lt_vtri[fidx]];
3632     minmax_v2v2_v2(min, max, vCoSS);
3633   } while (fidx--);
3634 
3635   project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
3636 
3637   for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
3638     has_x_isect = 0;
3639     for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
3640       if (project_bucket_face_isect(ps, bucket_x, bucket_y, lt)) {
3641         int bucket_index = bucket_x + (bucket_y * ps->buckets_x);
3642         BLI_linklist_prepend_arena(&ps->bucketFaces[bucket_index],
3643                                    /* cast to a pointer to shut up the compiler */
3644                                    POINTER_FROM_INT(tri_index),
3645                                    arena);
3646 
3647         has_x_isect = has_isect = 1;
3648       }
3649       else if (has_x_isect) {
3650         /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
3651         break;
3652       }
3653     }
3654 
3655     /* no intersection for this entire row,
3656      * after some intersection above means we can quit now */
3657     if (has_x_isect == 0 && has_isect) {
3658       break;
3659     }
3660   }
3661 
3662 #ifndef PROJ_DEBUG_NOSEAMBLEED
3663   if (ps->seam_bleed_px > 0.0f) {
3664     /* set as uninitialized */
3665     ps->loopSeamData[lt->tri[0]].seam_uvs[0][0] = FLT_MAX;
3666     ps->loopSeamData[lt->tri[1]].seam_uvs[0][0] = FLT_MAX;
3667     ps->loopSeamData[lt->tri[2]].seam_uvs[0][0] = FLT_MAX;
3668   }
3669 #endif
3670 }
3671 
proj_paint_state_viewport_init(ProjPaintState * ps,const char symmetry_flag)3672 static void proj_paint_state_viewport_init(ProjPaintState *ps, const char symmetry_flag)
3673 {
3674   float mat[3][3];
3675   float viewmat[4][4];
3676   float viewinv[4][4];
3677 
3678   ps->viewDir[0] = 0.0f;
3679   ps->viewDir[1] = 0.0f;
3680   ps->viewDir[2] = 1.0f;
3681 
3682   copy_m4_m4(ps->obmat, ps->ob->obmat);
3683 
3684   if (symmetry_flag) {
3685     int i;
3686     for (i = 0; i < 3; i++) {
3687       if ((symmetry_flag >> i) & 1) {
3688         negate_v3(ps->obmat[i]);
3689         ps->is_flip_object = !ps->is_flip_object;
3690       }
3691     }
3692   }
3693 
3694   invert_m4_m4(ps->obmat_imat, ps->obmat);
3695 
3696   if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
3697     /* normal drawing */
3698     ps->winx = ps->region->winx;
3699     ps->winy = ps->region->winy;
3700 
3701     copy_m4_m4(viewmat, ps->rv3d->viewmat);
3702     copy_m4_m4(viewinv, ps->rv3d->viewinv);
3703 
3704     ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat);
3705 
3706     ps->is_ortho = ED_view3d_clip_range_get(
3707         ps->depsgraph, ps->v3d, ps->rv3d, &ps->clip_start, &ps->clip_end, true);
3708   }
3709   else {
3710     /* re-projection */
3711     float winmat[4][4];
3712     float vmat[4][4];
3713 
3714     ps->winx = ps->reproject_ibuf->x;
3715     ps->winy = ps->reproject_ibuf->y;
3716 
3717     if (ps->source == PROJ_SRC_IMAGE_VIEW) {
3718       /* image stores camera data, tricky */
3719       IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0);
3720       IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
3721 
3722       const float *array = (float *)IDP_Array(view_data);
3723 
3724       /* use image array, written when creating image */
3725       memcpy(winmat, array, sizeof(winmat));
3726       array += sizeof(winmat) / sizeof(float);
3727       memcpy(viewmat, array, sizeof(viewmat));
3728       array += sizeof(viewmat) / sizeof(float);
3729       ps->clip_start = array[0];
3730       ps->clip_end = array[1];
3731       ps->is_ortho = array[2] ? 1 : 0;
3732 
3733       invert_m4_m4(viewinv, viewmat);
3734     }
3735     else if (ps->source == PROJ_SRC_IMAGE_CAM) {
3736       Object *cam_ob_eval = DEG_get_evaluated_object(ps->depsgraph, ps->scene->camera);
3737       CameraParams params;
3738 
3739       /* viewmat & viewinv */
3740       copy_m4_m4(viewinv, cam_ob_eval->obmat);
3741       normalize_m4(viewinv);
3742       invert_m4_m4(viewmat, viewinv);
3743 
3744       /* window matrix, clipping and ortho */
3745       BKE_camera_params_init(&params);
3746       BKE_camera_params_from_object(&params, cam_ob_eval);
3747       BKE_camera_params_compute_viewplane(&params, ps->winx, ps->winy, 1.0f, 1.0f);
3748       BKE_camera_params_compute_matrix(&params);
3749 
3750       copy_m4_m4(winmat, params.winmat);
3751       ps->clip_start = params.clip_start;
3752       ps->clip_end = params.clip_end;
3753       ps->is_ortho = params.is_ortho;
3754     }
3755     else {
3756       BLI_assert(0);
3757     }
3758 
3759     /* same as #ED_view3d_ob_project_mat_get */
3760     mul_m4_m4m4(vmat, viewmat, ps->obmat);
3761     mul_m4_m4m4(ps->projectMat, winmat, vmat);
3762   }
3763 
3764   invert_m4_m4(ps->projectMatInv, ps->projectMat);
3765 
3766   /* viewDir - object relative */
3767   copy_m3_m4(mat, viewinv);
3768   mul_m3_v3(mat, ps->viewDir);
3769   copy_m3_m4(mat, ps->obmat_imat);
3770   mul_m3_v3(mat, ps->viewDir);
3771   normalize_v3(ps->viewDir);
3772 
3773   if (UNLIKELY(ps->is_flip_object)) {
3774     negate_v3(ps->viewDir);
3775   }
3776 
3777   /* viewPos - object relative */
3778   copy_v3_v3(ps->viewPos, viewinv[3]);
3779   copy_m3_m4(mat, ps->obmat_imat);
3780   mul_m3_v3(mat, ps->viewPos);
3781   add_v3_v3(ps->viewPos, ps->obmat_imat[3]);
3782 }
3783 
proj_paint_state_screen_coords_init(ProjPaintState * ps,const int diameter)3784 static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter)
3785 {
3786   const MVert *mv;
3787   float *projScreenCo;
3788   float projMargin;
3789   int a;
3790 
3791   INIT_MINMAX2(ps->screenMin, ps->screenMax);
3792 
3793   ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts");
3794   projScreenCo = *ps->screenCoords;
3795 
3796   if (ps->is_ortho) {
3797     for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
3798       mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
3799 
3800       /* screen space, not clamped */
3801       projScreenCo[0] = (float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projScreenCo[0];
3802       projScreenCo[1] = (float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projScreenCo[1];
3803       minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
3804     }
3805   }
3806   else {
3807     for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
3808       copy_v3_v3(projScreenCo, mv->co);
3809       projScreenCo[3] = 1.0f;
3810 
3811       mul_m4_v4(ps->projectMat, projScreenCo);
3812 
3813       if (projScreenCo[3] > ps->clip_start) {
3814         /* screen space, not clamped */
3815         projScreenCo[0] = (float)(ps->winx * 0.5f) +
3816                           (ps->winx * 0.5f) * projScreenCo[0] / projScreenCo[3];
3817         projScreenCo[1] = (float)(ps->winy * 0.5f) +
3818                           (ps->winy * 0.5f) * projScreenCo[1] / projScreenCo[3];
3819         /* Use the depth for bucket point occlusion */
3820         projScreenCo[2] = projScreenCo[2] / projScreenCo[3];
3821         minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo);
3822       }
3823       else {
3824         /* TODO - deal with cases where 1 side of a face goes behind the view ?
3825          *
3826          * After some research this is actually very tricky, only option is to
3827          * clip the derived mesh before painting, which is a Pain */
3828         projScreenCo[0] = FLT_MAX;
3829       }
3830     }
3831   }
3832 
3833   /* If this border is not added we get artifacts for faces that
3834    * have a parallel edge and at the bounds of the 2D projected verts eg
3835    * - a single screen aligned quad */
3836   projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
3837   ps->screenMax[0] += projMargin;
3838   ps->screenMin[0] -= projMargin;
3839   projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
3840   ps->screenMax[1] += projMargin;
3841   ps->screenMin[1] -= projMargin;
3842 
3843   if (ps->source == PROJ_SRC_VIEW) {
3844 #ifdef PROJ_DEBUG_WINCLIP
3845     CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
3846     CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
3847 
3848     CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
3849     CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
3850 #else
3851     UNUSED_VARS(diameter);
3852 #endif
3853   }
3854   else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */
3855     ps->screenMin[0] = 0;
3856     ps->screenMax[0] = (float)(ps->winx);
3857 
3858     ps->screenMin[1] = 0;
3859     ps->screenMax[1] = (float)(ps->winy);
3860   }
3861 }
3862 
proj_paint_state_cavity_init(ProjPaintState * ps)3863 static void proj_paint_state_cavity_init(ProjPaintState *ps)
3864 {
3865   const MVert *mv;
3866   const MEdge *me;
3867   float *cavities;
3868   int a;
3869 
3870   if (ps->do_mask_cavity) {
3871     int *counter = MEM_callocN(sizeof(int) * ps->totvert_eval, "counter");
3872     float(*edges)[3] = MEM_callocN(sizeof(float[3]) * ps->totvert_eval, "edges");
3873     ps->cavities = MEM_mallocN(sizeof(float) * ps->totvert_eval, "ProjectPaint Cavities");
3874     cavities = ps->cavities;
3875 
3876     for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) {
3877       float e[3];
3878       sub_v3_v3v3(e, ps->mvert_eval[me->v1].co, ps->mvert_eval[me->v2].co);
3879       normalize_v3(e);
3880       add_v3_v3(edges[me->v2], e);
3881       counter[me->v2]++;
3882       sub_v3_v3(edges[me->v1], e);
3883       counter[me->v1]++;
3884     }
3885     for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
3886       if (counter[a] > 0) {
3887         float no[3];
3888         mul_v3_fl(edges[a], 1.0f / counter[a]);
3889         normal_short_to_float_v3(no, mv->no);
3890         /* augment the diffe*/
3891         cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI;
3892       }
3893       else {
3894         cavities[a] = 0.0;
3895       }
3896     }
3897 
3898     MEM_freeN(counter);
3899     MEM_freeN(edges);
3900   }
3901 }
3902 
3903 #ifndef PROJ_DEBUG_NOSEAMBLEED
proj_paint_state_seam_bleed_init(ProjPaintState * ps)3904 static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
3905 {
3906   if (ps->seam_bleed_px > 0.0f) {
3907     ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces");
3908     ps->faceSeamFlags = MEM_callocN(sizeof(ushort) * ps->totlooptri_eval, "paint-faceSeamFlags");
3909     ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval,
3910                                        "paint-faceWindindFlags");
3911     ps->loopSeamData = MEM_mallocN(sizeof(LoopSeamData) * ps->totloop_eval, "paint-loopSeamUVs");
3912     ps->vertSeams = MEM_callocN(sizeof(ListBase) * ps->totvert_eval, "paint-vertSeams");
3913   }
3914 }
3915 #endif
3916 
proj_paint_state_thread_init(ProjPaintState * ps,const bool reset_threads)3917 static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_threads)
3918 {
3919   /* Thread stuff
3920    *
3921    * very small brushes run a lot slower multi-threaded since the advantage with
3922    * threads is being able to fill in multiple buckets at once.
3923    * Only use threads for bigger brushes. */
3924 
3925   ps->thread_tot = BKE_scene_num_threads(ps->scene);
3926 
3927   /* workaround for T35057, disable threading if diameter is less than is possible for
3928    * optimum bucket number generation */
3929   if (reset_threads) {
3930     ps->thread_tot = 1;
3931   }
3932 
3933   if (ps->is_shared_user == false) {
3934     if (ps->thread_tot > 1) {
3935       ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock");
3936       BLI_spin_init(ps->tile_lock);
3937     }
3938 
3939     ED_image_paint_tile_lock_init();
3940   }
3941 
3942   for (int a = 0; a < ps->thread_tot; a++) {
3943     ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena");
3944   }
3945 }
3946 
proj_paint_state_vert_flags_init(ProjPaintState * ps)3947 static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
3948 {
3949   if (ps->do_backfacecull && ps->do_mask_normal) {
3950     float viewDirPersp[3];
3951     const MVert *mv;
3952     float no[3];
3953     int a;
3954 
3955     ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
3956 
3957     for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
3958       normal_short_to_float_v3(no, mv->no);
3959       if (UNLIKELY(ps->is_flip_object)) {
3960         negate_v3(no);
3961       }
3962 
3963       if (ps->is_ortho) {
3964         if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) {
3965           /* 1 vert of this face is towards us */
3966           ps->vertFlags[a] |= PROJ_VERT_CULL;
3967         }
3968       }
3969       else {
3970         sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co);
3971         normalize_v3(viewDirPersp);
3972         if (UNLIKELY(ps->is_flip_object)) {
3973           negate_v3(viewDirPersp);
3974         }
3975         if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) {
3976           /* 1 vert of this face is towards us */
3977           ps->vertFlags[a] |= PROJ_VERT_CULL;
3978         }
3979       }
3980     }
3981   }
3982   else {
3983     ps->vertFlags = NULL;
3984   }
3985 }
3986 
3987 #ifndef PROJ_DEBUG_NOSEAMBLEED
project_paint_bleed_add_face_user(const ProjPaintState * ps,MemArena * arena,const MLoopTri * lt,const int tri_index)3988 static void project_paint_bleed_add_face_user(const ProjPaintState *ps,
3989                                               MemArena *arena,
3990                                               const MLoopTri *lt,
3991                                               const int tri_index)
3992 {
3993   /* add face user if we have bleed enabled, set the UV seam flags later */
3994   /* annoying but we need to add all faces even ones we never use elsewhere */
3995   if (ps->seam_bleed_px > 0.0f) {
3996     const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
3997 
3998     /* Check for degenerate triangles. Degenerate faces cause trouble with bleed computations.
3999      * Ideally this would be checked later, not to add to the cost of computing non-degenerate
4000      * triangles, but that would allow other triangles to still find adjacent seams on degenerate
4001      * triangles, potentially causing incorrect results. */
4002     if (area_tri_v2(UNPACK3(lt_tri_uv)) > 0.0f) {
4003       const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
4004       void *tri_index_p = POINTER_FROM_INT(tri_index);
4005 
4006       BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[0]], tri_index_p, arena);
4007       BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[1]], tri_index_p, arena);
4008       BLI_linklist_prepend_arena(&ps->vertFaces[lt_vtri[2]], tri_index_p, arena);
4009     }
4010     else {
4011       ps->faceSeamFlags[tri_index] |= PROJ_FACE_DEGENERATE;
4012     }
4013   }
4014 }
4015 #endif
4016 
4017 /* Return true if evaluated mesh can be painted on, false otherwise */
proj_paint_state_mesh_eval_init(const bContext * C,ProjPaintState * ps)4018 static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *ps)
4019 {
4020   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
4021   Object *ob = ps->ob;
4022 
4023   Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
4024   Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
4025 
4026   if (scene_eval == NULL || ob_eval == NULL) {
4027     return false;
4028   }
4029 
4030   CustomData_MeshMasks cddata_masks = scene_eval->customdata_mask;
4031   cddata_masks.fmask |= CD_MASK_MTFACE;
4032   cddata_masks.lmask |= CD_MASK_MLOOPUV;
4033   if (ps->do_face_sel) {
4034     cddata_masks.vmask |= CD_MASK_ORIGINDEX;
4035     cddata_masks.emask |= CD_MASK_ORIGINDEX;
4036     cddata_masks.pmask |= CD_MASK_ORIGINDEX;
4037   }
4038   ps->me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
4039 
4040   if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
4041     ps->me_eval = NULL;
4042     return false;
4043   }
4044 
4045   /* Build final material array, we use this a lot here. */
4046   /* materials start from 1, default material is 0 */
4047   const int totmat = ob->totcol + 1;
4048   ps->mat_array = MEM_malloc_arrayN(totmat, sizeof(*ps->mat_array), __func__);
4049   /* We leave last material as empty - rationale here is being able to index
4050    * the materials by using the mf->mat_nr directly and leaving the last
4051    * material as NULL in case no materials exist on mesh, so indexing will not fail. */
4052   for (int i = 0; i < totmat - 1; i++) {
4053     ps->mat_array[i] = BKE_object_material_get(ob, i + 1);
4054   }
4055   ps->mat_array[totmat - 1] = NULL;
4056 
4057   ps->mvert_eval = ps->me_eval->mvert;
4058   if (ps->do_mask_cavity) {
4059     ps->medge_eval = ps->me_eval->medge;
4060   }
4061   ps->mloop_eval = ps->me_eval->mloop;
4062   ps->mpoly_eval = ps->me_eval->mpoly;
4063 
4064   ps->totvert_eval = ps->me_eval->totvert;
4065   ps->totedge_eval = ps->me_eval->totedge;
4066   ps->totpoly_eval = ps->me_eval->totpoly;
4067   ps->totloop_eval = ps->me_eval->totloop;
4068 
4069   ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
4070   ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
4071 
4072   ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
4073 
4074   return true;
4075 }
4076 
4077 typedef struct {
4078   const MLoopUV *mloopuv_clone_base;
4079   const TexPaintSlot *slot_last_clone;
4080   const TexPaintSlot *slot_clone;
4081 } ProjPaintLayerClone;
4082 
proj_paint_layer_clone_init(ProjPaintState * ps,ProjPaintLayerClone * layer_clone)4083 static void proj_paint_layer_clone_init(ProjPaintState *ps, ProjPaintLayerClone *layer_clone)
4084 {
4085   MLoopUV *mloopuv_clone_base = NULL;
4086 
4087   /* use clone mtface? */
4088   if (ps->do_layer_clone) {
4089     const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
4090 
4091     ps->poly_to_loop_uv_clone = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *),
4092                                             "proj_paint_mtfaces");
4093 
4094     if (layer_num != -1) {
4095       mloopuv_clone_base = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
4096     }
4097 
4098     if (mloopuv_clone_base == NULL) {
4099       /* get active instead */
4100       mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
4101     }
4102   }
4103 
4104   memset(layer_clone, 0, sizeof(*layer_clone));
4105   layer_clone->mloopuv_clone_base = mloopuv_clone_base;
4106 }
4107 
4108 /* Return true if face should be skipped, false otherwise */
project_paint_clone_face_skip(ProjPaintState * ps,ProjPaintLayerClone * lc,const TexPaintSlot * slot,const int tri_index)4109 static bool project_paint_clone_face_skip(ProjPaintState *ps,
4110                                           ProjPaintLayerClone *lc,
4111                                           const TexPaintSlot *slot,
4112                                           const int tri_index)
4113 {
4114   if (ps->do_layer_clone) {
4115     if (ps->do_material_slots) {
4116       lc->slot_clone = project_paint_face_clone_slot(ps, tri_index);
4117       /* all faces should have a valid slot, reassert here */
4118       if (ELEM(lc->slot_clone, NULL, slot)) {
4119         return true;
4120       }
4121     }
4122     else if (ps->clone_ima == ps->canvas_ima) {
4123       return true;
4124     }
4125 
4126     if (ps->do_material_slots) {
4127       if (lc->slot_clone != lc->slot_last_clone) {
4128         if (!slot->uvname || !(lc->mloopuv_clone_base = CustomData_get_layer_named(
4129                                    &ps->me_eval->ldata, CD_MLOOPUV, lc->slot_clone->uvname))) {
4130           lc->mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
4131         }
4132         lc->slot_last_clone = lc->slot_clone;
4133       }
4134     }
4135 
4136     /* will set multiple times for 4+ sided poly */
4137     ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
4138   }
4139   return false;
4140 }
4141 
4142 typedef struct {
4143   const MPoly *mpoly_orig;
4144 
4145   const int *index_mp_to_orig;
4146 } ProjPaintFaceLookup;
4147 
proj_paint_face_lookup_init(const ProjPaintState * ps,ProjPaintFaceLookup * face_lookup)4148 static void proj_paint_face_lookup_init(const ProjPaintState *ps, ProjPaintFaceLookup *face_lookup)
4149 {
4150   memset(face_lookup, 0, sizeof(*face_lookup));
4151   if (ps->do_face_sel) {
4152     face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
4153     face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
4154   }
4155 }
4156 
4157 /* Return true if face should be considered selected, false otherwise */
project_paint_check_face_sel(const ProjPaintState * ps,const ProjPaintFaceLookup * face_lookup,const MLoopTri * lt)4158 static bool project_paint_check_face_sel(const ProjPaintState *ps,
4159                                          const ProjPaintFaceLookup *face_lookup,
4160                                          const MLoopTri *lt)
4161 {
4162   if (ps->do_face_sel) {
4163     int orig_index;
4164     const MPoly *mp;
4165 
4166     if ((face_lookup->index_mp_to_orig != NULL) &&
4167         (((orig_index = (face_lookup->index_mp_to_orig[lt->poly]))) != ORIGINDEX_NONE)) {
4168       mp = &face_lookup->mpoly_orig[orig_index];
4169     }
4170     else {
4171       mp = &ps->mpoly_eval[lt->poly];
4172     }
4173 
4174     return ((mp->flag & ME_FACE_SEL) != 0);
4175   }
4176   return true;
4177 }
4178 
4179 typedef struct {
4180   const float *v1;
4181   const float *v2;
4182   const float *v3;
4183 } ProjPaintFaceCoSS;
4184 
proj_paint_face_coSS_init(const ProjPaintState * ps,const MLoopTri * lt,ProjPaintFaceCoSS * coSS)4185 static void proj_paint_face_coSS_init(const ProjPaintState *ps,
4186                                       const MLoopTri *lt,
4187                                       ProjPaintFaceCoSS *coSS)
4188 {
4189   const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
4190   coSS->v1 = ps->screenCoords[lt_vtri[0]];
4191   coSS->v2 = ps->screenCoords[lt_vtri[1]];
4192   coSS->v3 = ps->screenCoords[lt_vtri[2]];
4193 }
4194 
4195 /* Return true if face should be culled, false otherwise */
project_paint_flt_max_cull(const ProjPaintState * ps,const ProjPaintFaceCoSS * coSS)4196 static bool project_paint_flt_max_cull(const ProjPaintState *ps, const ProjPaintFaceCoSS *coSS)
4197 {
4198   if (!ps->is_ortho) {
4199     if (coSS->v1[0] == FLT_MAX || coSS->v2[0] == FLT_MAX || coSS->v3[0] == FLT_MAX) {
4200       return true;
4201     }
4202   }
4203   return false;
4204 }
4205 
4206 #ifdef PROJ_DEBUG_WINCLIP
4207 /* Return true if face should be culled, false otherwise */
project_paint_winclip(const ProjPaintState * ps,const ProjPaintFaceCoSS * coSS)4208 static bool project_paint_winclip(const ProjPaintState *ps, const ProjPaintFaceCoSS *coSS)
4209 {
4210   /* ignore faces outside the view */
4211   return ((ps->source != PROJ_SRC_VIEW_FILL) &&
4212           ((coSS->v1[0] < ps->screenMin[0] && coSS->v2[0] < ps->screenMin[0] &&
4213             coSS->v3[0] < ps->screenMin[0]) ||
4214 
4215            (coSS->v1[0] > ps->screenMax[0] && coSS->v2[0] > ps->screenMax[0] &&
4216             coSS->v3[0] > ps->screenMax[0]) ||
4217 
4218            (coSS->v1[1] < ps->screenMin[1] && coSS->v2[1] < ps->screenMin[1] &&
4219             coSS->v3[1] < ps->screenMin[1]) ||
4220 
4221            (coSS->v1[1] > ps->screenMax[1] && coSS->v2[1] > ps->screenMax[1] &&
4222             coSS->v3[1] > ps->screenMax[1])));
4223 }
4224 #endif /* PROJ_DEBUG_WINCLIP */
4225 
4226 typedef struct PrepareImageEntry {
4227   struct PrepareImageEntry *next, *prev;
4228   Image *ima;
4229   ImageUser iuser;
4230 } PrepareImageEntry;
4231 
project_paint_build_proj_ima(ProjPaintState * ps,MemArena * arena,ListBase * used_images)4232 static void project_paint_build_proj_ima(ProjPaintState *ps,
4233                                          MemArena *arena,
4234                                          ListBase *used_images)
4235 {
4236   ProjPaintImage *projIma;
4237   PrepareImageEntry *entry;
4238   int i;
4239 
4240   /* build an array of images we use */
4241   projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
4242 
4243   for (entry = used_images->first, i = 0; entry; entry = entry->next, i++, projIma++) {
4244     projIma->iuser = entry->iuser;
4245     int size;
4246     projIma->ima = entry->ima;
4247     projIma->touch = 0;
4248     projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, &projIma->iuser, NULL);
4249     if (projIma->ibuf == NULL) {
4250       projIma->iuser.tile = 0;
4251       projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, &projIma->iuser, NULL);
4252       BLI_assert(projIma->ibuf != NULL);
4253     }
4254     size = sizeof(void **) * ED_IMAGE_UNDO_TILE_NUMBER(projIma->ibuf->x) *
4255            ED_IMAGE_UNDO_TILE_NUMBER(projIma->ibuf->y);
4256     projIma->partRedrawRect = BLI_memarena_alloc(
4257         arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
4258     partial_redraw_array_init(projIma->partRedrawRect);
4259     projIma->undoRect = (volatile void **)BLI_memarena_alloc(arena, size);
4260     memset((void *)projIma->undoRect, 0, size);
4261     projIma->maskRect = BLI_memarena_alloc(arena, size);
4262     memset(projIma->maskRect, 0, size);
4263     projIma->valid = BLI_memarena_alloc(arena, size);
4264     memset(projIma->valid, 0, size);
4265   }
4266 }
4267 
project_paint_prepare_all_faces(ProjPaintState * ps,MemArena * arena,const ProjPaintFaceLookup * face_lookup,ProjPaintLayerClone * layer_clone,const MLoopUV * mloopuv_base,const bool is_multi_view)4268 static void project_paint_prepare_all_faces(ProjPaintState *ps,
4269                                             MemArena *arena,
4270                                             const ProjPaintFaceLookup *face_lookup,
4271                                             ProjPaintLayerClone *layer_clone,
4272                                             const MLoopUV *mloopuv_base,
4273                                             const bool is_multi_view)
4274 {
4275   /* Image Vars - keep track of images we have used */
4276   ListBase used_images = {NULL};
4277 
4278   Image *tpage_last = NULL, *tpage;
4279   TexPaintSlot *slot_last = NULL;
4280   TexPaintSlot *slot = NULL;
4281   int tile_last = -1, tile;
4282   const MLoopTri *lt;
4283   int image_index = -1, tri_index;
4284   int prev_poly = -1;
4285 
4286   BLI_assert(ps->image_tot == 0);
4287 
4288   for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
4289     bool is_face_sel;
4290     bool skip_tri = false;
4291 
4292     is_face_sel = project_paint_check_face_sel(ps, face_lookup, lt);
4293 
4294     if (!ps->do_stencil_brush) {
4295       slot = project_paint_face_paint_slot(ps, tri_index);
4296       /* all faces should have a valid slot, reassert here */
4297       if (slot == NULL) {
4298         mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
4299         tpage = ps->canvas_ima;
4300       }
4301       else {
4302         if (slot != slot_last) {
4303           if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(
4304                                      &ps->me_eval->ldata, CD_MLOOPUV, slot->uvname))) {
4305             mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
4306           }
4307           slot_last = slot;
4308         }
4309 
4310         /* don't allow using the same inage for painting and stencilling */
4311         if (slot->ima == ps->stencil_ima) {
4312           /* Delay continuing the loop until after loop_uvs and bleed faces are initialized.
4313            * While this shouldn't be used, face-winding reads all polys.
4314            * It's less trouble to set all faces to valid UV's,
4315            * avoiding NULL checks all over. */
4316           skip_tri = true;
4317           tpage = NULL;
4318         }
4319         else {
4320           tpage = slot->ima;
4321         }
4322       }
4323     }
4324     else {
4325       tpage = ps->stencil_ima;
4326     }
4327 
4328     ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
4329 
4330     tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]].uv);
4331 
4332 #ifndef PROJ_DEBUG_NOSEAMBLEED
4333     project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
4334 #endif
4335 
4336     if (skip_tri || project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
4337       continue;
4338     }
4339 
4340     /* tfbase here should be non-null! */
4341     BLI_assert(mloopuv_base != NULL);
4342 
4343     if (is_face_sel && tpage) {
4344       ProjPaintFaceCoSS coSS;
4345       proj_paint_face_coSS_init(ps, lt, &coSS);
4346 
4347       if (is_multi_view == false) {
4348         if (project_paint_flt_max_cull(ps, &coSS)) {
4349           continue;
4350         }
4351 
4352 #ifdef PROJ_DEBUG_WINCLIP
4353         if (project_paint_winclip(ps, &coSS)) {
4354           continue;
4355         }
4356 
4357 #endif  // PROJ_DEBUG_WINCLIP
4358 
4359         /* backface culls individual triangles but mask normal will use polygon */
4360         if (ps->do_backfacecull) {
4361           if (ps->do_mask_normal) {
4362             if (prev_poly != lt->poly) {
4363               int iloop;
4364               bool culled = true;
4365               const MPoly *poly = ps->mpoly_eval + lt->poly;
4366               int poly_loops = poly->totloop;
4367               prev_poly = lt->poly;
4368               for (iloop = 0; iloop < poly_loops; iloop++) {
4369                 if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
4370                   culled = false;
4371                   break;
4372                 }
4373               }
4374 
4375               if (culled) {
4376                 /* poly loops - 2 is number of triangles for poly,
4377                  * but counter gets incremented when continuing, so decrease by 3 */
4378                 int poly_tri = poly_loops - 3;
4379                 tri_index += poly_tri;
4380                 lt += poly_tri;
4381                 continue;
4382               }
4383             }
4384           }
4385           else {
4386             if ((line_point_side_v2(coSS.v1, coSS.v2, coSS.v3) < 0.0f) != ps->is_flip_object) {
4387               continue;
4388             }
4389           }
4390         }
4391       }
4392 
4393       if (tpage_last != tpage || tile_last != tile) {
4394         image_index = 0;
4395         for (PrepareImageEntry *e = used_images.first; e; e = e->next, image_index++) {
4396           if (e->ima == tpage && e->iuser.tile == tile) {
4397             break;
4398           }
4399         }
4400 
4401         if (image_index == ps->image_tot) {
4402           /* XXX get appropriate ImageUser instead */
4403           ImageUser iuser;
4404           BKE_imageuser_default(&iuser);
4405           iuser.tile = tile;
4406           iuser.framenr = tpage->lastframe;
4407           if (BKE_image_has_ibuf(tpage, &iuser)) {
4408             PrepareImageEntry *e = MEM_callocN(sizeof(PrepareImageEntry), "PrepareImageEntry");
4409             e->ima = tpage;
4410             e->iuser = iuser;
4411             BLI_addtail(&used_images, e);
4412             ps->image_tot++;
4413           }
4414           else {
4415             image_index = -1;
4416           }
4417         }
4418 
4419         tpage_last = tpage;
4420         tile_last = tile;
4421       }
4422 
4423       if (image_index != -1) {
4424         /* Initialize the faces screen pixels */
4425         /* Add this to a list to initialize later */
4426         project_paint_delayed_face_init(ps, lt, tri_index);
4427       }
4428     }
4429   }
4430 
4431   /* build an array of images we use*/
4432   if (ps->is_shared_user == false) {
4433     project_paint_build_proj_ima(ps, arena, &used_images);
4434   }
4435 
4436   /* we have built the array, discard the linked list */
4437   BLI_freelistN(&used_images);
4438 }
4439 
4440 /* run once per stroke before projection painting */
project_paint_begin(const bContext * C,ProjPaintState * ps,const bool is_multi_view,const char symmetry_flag)4441 static void project_paint_begin(const bContext *C,
4442                                 ProjPaintState *ps,
4443                                 const bool is_multi_view,
4444                                 const char symmetry_flag)
4445 {
4446   ProjPaintLayerClone layer_clone;
4447   ProjPaintFaceLookup face_lookup;
4448   const MLoopUV *mloopuv_base = NULL;
4449 
4450   /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
4451   MemArena *arena;
4452 
4453   const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
4454 
4455   bool reset_threads = false;
4456 
4457   /* ---- end defines ---- */
4458 
4459   if (ps->source == PROJ_SRC_VIEW) {
4460     /* faster clipping lookups */
4461     ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat);
4462   }
4463 
4464   ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
4465   ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0;
4466 
4467   /* paint onto the derived mesh */
4468   if (ps->is_shared_user == false) {
4469     if (!proj_paint_state_mesh_eval_init(C, ps)) {
4470       return;
4471     }
4472   }
4473 
4474   proj_paint_face_lookup_init(ps, &face_lookup);
4475   proj_paint_layer_clone_init(ps, &layer_clone);
4476 
4477   if (ps->do_layer_stencil || ps->do_stencil_brush) {
4478     // int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV);
4479     int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
4480     if (layer_num != -1) {
4481       ps->mloopuv_stencil_eval = CustomData_get_layer_n(
4482           &ps->me_eval->ldata, CD_MLOOPUV, layer_num);
4483     }
4484 
4485     if (ps->mloopuv_stencil_eval == NULL) {
4486       /* get active instead */
4487       ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
4488     }
4489 
4490     if (ps->do_stencil_brush) {
4491       mloopuv_base = ps->mloopuv_stencil_eval;
4492     }
4493   }
4494 
4495   /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
4496   if (ps->is_shared_user == false) {
4497     proj_paint_state_cavity_init(ps);
4498   }
4499 
4500   proj_paint_state_viewport_init(ps, symmetry_flag);
4501 
4502   /* calculate vert screen coords
4503    * run this early so we can calculate the x/y resolution of our bucket rect */
4504   proj_paint_state_screen_coords_init(ps, diameter);
4505 
4506   /* only for convenience */
4507   ps->screen_width = ps->screenMax[0] - ps->screenMin[0];
4508   ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
4509 
4510   ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
4511   ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
4512 
4513   /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
4514 
4515   if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
4516     reset_threads = true;
4517   }
4518 
4519   /* really high values could cause problems since it has to allocate a few
4520    * (ps->buckets_x*ps->buckets_y) sized arrays  */
4521   CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
4522   CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
4523 
4524   ps->bucketRect = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y,
4525                                "paint-bucketRect");
4526   ps->bucketFaces = MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y,
4527                                 "paint-bucketFaces");
4528 
4529   ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
4530 #ifndef PROJ_DEBUG_NOSEAMBLEED
4531   if (ps->is_shared_user == false) {
4532     proj_paint_state_seam_bleed_init(ps);
4533   }
4534 #endif
4535 
4536   proj_paint_state_thread_init(ps, reset_threads);
4537   arena = ps->arena_mt[0];
4538 
4539   proj_paint_state_vert_flags_init(ps);
4540 
4541   project_paint_prepare_all_faces(
4542       ps, arena, &face_lookup, &layer_clone, mloopuv_base, is_multi_view);
4543 }
4544 
paint_proj_begin_clone(ProjPaintState * ps,const float mouse[2])4545 static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2])
4546 {
4547   /* setup clone offset */
4548   if (ps->tool == PAINT_TOOL_CLONE) {
4549     float projCo[4];
4550     copy_v3_v3(projCo, ps->scene->cursor.location);
4551     mul_m4_v3(ps->obmat_imat, projCo);
4552 
4553     projCo[3] = 1.0f;
4554     mul_m4_v4(ps->projectMat, projCo);
4555     ps->cloneOffset[0] = mouse[0] -
4556                          ((float)(ps->winx * 0.5f) + (ps->winx * 0.5f) * projCo[0] / projCo[3]);
4557     ps->cloneOffset[1] = mouse[1] -
4558                          ((float)(ps->winy * 0.5f) + (ps->winy * 0.5f) * projCo[1] / projCo[3]);
4559   }
4560 }
4561 
project_paint_end(ProjPaintState * ps)4562 static void project_paint_end(ProjPaintState *ps)
4563 {
4564   int a;
4565 
4566   /* dereference used image buffers */
4567   if (ps->is_shared_user == false) {
4568     ProjPaintImage *projIma;
4569     for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
4570       BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL);
4571       DEG_id_tag_update(&projIma->ima->id, 0);
4572     }
4573   }
4574 
4575   if (ps->reproject_ibuf_free_float) {
4576     imb_freerectfloatImBuf(ps->reproject_ibuf);
4577   }
4578   if (ps->reproject_ibuf_free_uchar) {
4579     imb_freerectImBuf(ps->reproject_ibuf);
4580   }
4581   BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL);
4582 
4583   MEM_freeN(ps->screenCoords);
4584   MEM_freeN(ps->bucketRect);
4585   MEM_freeN(ps->bucketFaces);
4586   MEM_freeN(ps->bucketFlags);
4587 
4588   if (ps->is_shared_user == false) {
4589     if (ps->mat_array != NULL) {
4590       MEM_freeN(ps->mat_array);
4591     }
4592 
4593     /* must be set for non-shared */
4594     BLI_assert(ps->poly_to_loop_uv || ps->is_shared_user);
4595     if (ps->poly_to_loop_uv) {
4596       MEM_freeN((void *)ps->poly_to_loop_uv);
4597     }
4598 
4599     if (ps->do_layer_clone) {
4600       MEM_freeN((void *)ps->poly_to_loop_uv_clone);
4601     }
4602     if (ps->thread_tot > 1) {
4603       BLI_spin_end(ps->tile_lock);
4604       MEM_freeN((void *)ps->tile_lock);
4605     }
4606 
4607     ED_image_paint_tile_lock_end();
4608 
4609 #ifndef PROJ_DEBUG_NOSEAMBLEED
4610     if (ps->seam_bleed_px > 0.0f) {
4611       MEM_freeN(ps->vertFaces);
4612       MEM_freeN(ps->faceSeamFlags);
4613       MEM_freeN(ps->faceWindingFlags);
4614       MEM_freeN(ps->loopSeamData);
4615       MEM_freeN(ps->vertSeams);
4616     }
4617 #endif
4618 
4619     if (ps->do_mask_cavity) {
4620       MEM_freeN(ps->cavities);
4621     }
4622 
4623     ps->me_eval = NULL;
4624   }
4625 
4626   if (ps->blurkernel) {
4627     paint_delete_blur_kernel(ps->blurkernel);
4628     MEM_freeN(ps->blurkernel);
4629   }
4630 
4631   if (ps->vertFlags) {
4632     MEM_freeN(ps->vertFlags);
4633   }
4634 
4635   for (a = 0; a < ps->thread_tot; a++) {
4636     BLI_memarena_free(ps->arena_mt[a]);
4637   }
4638 }
4639 
4640 /* 1 = an undo, -1 is a redo. */
partial_redraw_single_init(ImagePaintPartialRedraw * pr)4641 static void partial_redraw_single_init(ImagePaintPartialRedraw *pr)
4642 {
4643   pr->x1 = INT_MAX;
4644   pr->y1 = INT_MAX;
4645 
4646   pr->x2 = -1;
4647   pr->y2 = -1;
4648 
4649   pr->enabled = 1;
4650 }
4651 
partial_redraw_array_init(ImagePaintPartialRedraw * pr)4652 static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
4653 {
4654   int tot = PROJ_BOUNDBOX_SQUARED;
4655   while (tot--) {
4656     partial_redraw_single_init(pr);
4657     pr++;
4658   }
4659 }
4660 
partial_redraw_array_merge(ImagePaintPartialRedraw * pr,ImagePaintPartialRedraw * pr_other,int tot)4661 static bool partial_redraw_array_merge(ImagePaintPartialRedraw *pr,
4662                                        ImagePaintPartialRedraw *pr_other,
4663                                        int tot)
4664 {
4665   bool touch = 0;
4666   while (tot--) {
4667     pr->x1 = min_ii(pr->x1, pr_other->x1);
4668     pr->y1 = min_ii(pr->y1, pr_other->y1);
4669 
4670     pr->x2 = max_ii(pr->x2, pr_other->x2);
4671     pr->y2 = max_ii(pr->y2, pr_other->y2);
4672 
4673     if (pr->x2 != -1) {
4674       touch = 1;
4675     }
4676 
4677     pr++;
4678     pr_other++;
4679   }
4680 
4681   return touch;
4682 }
4683 
4684 /* Loop over all images on this mesh and update any we have touched */
project_image_refresh_tagged(ProjPaintState * ps)4685 static bool project_image_refresh_tagged(ProjPaintState *ps)
4686 {
4687   ImagePaintPartialRedraw *pr;
4688   ProjPaintImage *projIma;
4689   int a, i;
4690   bool redraw = false;
4691 
4692   for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) {
4693     if (projIma->touch) {
4694       /* look over each bound cell */
4695       for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) {
4696         pr = &(projIma->partRedrawRect[i]);
4697         if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
4698           set_imapaintpartial(pr);
4699           imapaint_image_update(NULL, projIma->ima, projIma->ibuf, &projIma->iuser, true);
4700           redraw = 1;
4701         }
4702 
4703         partial_redraw_single_init(pr);
4704       }
4705 
4706       /* clear for reuse */
4707       projIma->touch = 0;
4708     }
4709   }
4710 
4711   return redraw;
4712 }
4713 
4714 /* run this per painting onto each mouse location */
project_bucket_iter_init(ProjPaintState * ps,const float mval_f[2])4715 static bool project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
4716 {
4717   if (ps->source == PROJ_SRC_VIEW) {
4718     float min_brush[2], max_brush[2];
4719     const float radius = ps->brush_size;
4720 
4721     /* so we don't have a bucket bounds that is way too small to paint into */
4722 #if 0
4723     /* This doesn't work yet. */
4724     if (radius < 1.0f) {
4725       radius = 1.0f;
4726     }
4727 #endif
4728 
4729     min_brush[0] = mval_f[0] - radius;
4730     min_brush[1] = mval_f[1] - radius;
4731 
4732     max_brush[0] = mval_f[0] + radius;
4733     max_brush[1] = mval_f[1] + radius;
4734 
4735     /* offset to make this a valid bucket index */
4736     project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
4737 
4738     /* mouse outside the model areas? */
4739     if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) {
4740       return false;
4741     }
4742   }
4743   else { /* reproject: PROJ_SRC_* */
4744     ps->bucketMin[0] = 0;
4745     ps->bucketMin[1] = 0;
4746 
4747     ps->bucketMax[0] = ps->buckets_x;
4748     ps->bucketMax[1] = ps->buckets_y;
4749   }
4750 
4751   ps->context_bucket_index = ps->bucketMin[0] + ps->bucketMin[1] * ps->buckets_x;
4752   return true;
4753 }
4754 
project_bucket_iter_next(ProjPaintState * ps,int * bucket_index,rctf * bucket_bounds,const float mval[2])4755 static bool project_bucket_iter_next(ProjPaintState *ps,
4756                                      int *bucket_index,
4757                                      rctf *bucket_bounds,
4758                                      const float mval[2])
4759 {
4760   const int diameter = 2 * ps->brush_size;
4761 
4762   const int max_bucket_idx = ps->bucketMax[0] + (ps->bucketMax[1] - 1) * ps->buckets_x;
4763 
4764   for (int bidx = atomic_fetch_and_add_int32(&ps->context_bucket_index, 1); bidx < max_bucket_idx;
4765        bidx = atomic_fetch_and_add_int32(&ps->context_bucket_index, 1)) {
4766     const int bucket_y = bidx / ps->buckets_x;
4767     const int bucket_x = bidx - (bucket_y * ps->buckets_x);
4768 
4769     BLI_assert(bucket_y >= ps->bucketMin[1] && bucket_y < ps->bucketMax[1]);
4770     if (bucket_x >= ps->bucketMin[0] && bucket_x < ps->bucketMax[0]) {
4771       /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
4772       project_bucket_bounds(ps, bucket_x, bucket_y, bucket_bounds);
4773 
4774       if ((ps->source != PROJ_SRC_VIEW) ||
4775           project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds)) {
4776         *bucket_index = bidx;
4777 
4778         return true;
4779       }
4780     }
4781   }
4782 
4783   return false;
4784 }
4785 
4786 /* Each thread gets one of these, also used as an argument to pass to project_paint_op */
4787 typedef struct ProjectHandle {
4788   /* args */
4789   ProjPaintState *ps;
4790   float prevmval[2];
4791   float mval[2];
4792 
4793   /* Annoying but we need to have image bounds per thread,
4794    * then merge into ps->projectPartialRedraws. */
4795 
4796   /* array of partial redraws */
4797   ProjPaintImage *projImages;
4798 
4799   /* thread settings */
4800   int thread_index;
4801 
4802   struct ImagePool *pool;
4803 } ProjectHandle;
4804 
do_projectpaint_clone(ProjPaintState * ps,ProjPixel * projPixel,float mask)4805 static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float mask)
4806 {
4807   const uchar *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.ch;
4808 
4809   if (clone_pt[3]) {
4810     uchar clone_rgba[4];
4811 
4812     clone_rgba[0] = clone_pt[0];
4813     clone_rgba[1] = clone_pt[1];
4814     clone_rgba[2] = clone_pt[2];
4815     clone_rgba[3] = (uchar)(clone_pt[3] * mask);
4816 
4817     if (ps->do_masking) {
4818       IMB_blend_color_byte(
4819           projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, clone_rgba, ps->blend);
4820     }
4821     else {
4822       IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, clone_rgba, ps->blend);
4823     }
4824   }
4825 }
4826 
do_projectpaint_clone_f(ProjPaintState * ps,ProjPixel * projPixel,float mask)4827 static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float mask)
4828 {
4829   const float *clone_pt = ((ProjPixelClone *)projPixel)->clonepx.f;
4830 
4831   if (clone_pt[3]) {
4832     float clone_rgba[4];
4833 
4834     mul_v4_v4fl(clone_rgba, clone_pt, mask);
4835 
4836     if (ps->do_masking) {
4837       IMB_blend_color_float(
4838           projPixel->pixel.f_pt, projPixel->origColor.f_pt, clone_rgba, ps->blend);
4839     }
4840     else {
4841       IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, clone_rgba, ps->blend);
4842     }
4843   }
4844 }
4845 
4846 /**
4847  * \note mask is used to modify the alpha here, this is not correct since it allows
4848  * accumulation of color greater than 'projPixel->mask' however in the case of smear its not
4849  * really that important to be correct as it is with clone and painting
4850  */
do_projectpaint_smear(ProjPaintState * ps,ProjPixel * projPixel,float mask,MemArena * smearArena,LinkNode ** smearPixels,const float co[2])4851 static void do_projectpaint_smear(ProjPaintState *ps,
4852                                   ProjPixel *projPixel,
4853                                   float mask,
4854                                   MemArena *smearArena,
4855                                   LinkNode **smearPixels,
4856                                   const float co[2])
4857 {
4858   uchar rgba_ub[4];
4859 
4860   if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0) {
4861     return;
4862   }
4863 
4864   blend_color_interpolate_byte(
4865       ((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, mask);
4866   BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
4867 }
4868 
do_projectpaint_smear_f(ProjPaintState * ps,ProjPixel * projPixel,float mask,MemArena * smearArena,LinkNode ** smearPixels_f,const float co[2])4869 static void do_projectpaint_smear_f(ProjPaintState *ps,
4870                                     ProjPixel *projPixel,
4871                                     float mask,
4872                                     MemArena *smearArena,
4873                                     LinkNode **smearPixels_f,
4874                                     const float co[2])
4875 {
4876   float rgba[4];
4877 
4878   if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0) {
4879     return;
4880   }
4881 
4882   blend_color_interpolate_float(
4883       ((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, mask);
4884   BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
4885 }
4886 
do_projectpaint_soften_f(ProjPaintState * ps,ProjPixel * projPixel,float mask,MemArena * softenArena,LinkNode ** softenPixels)4887 static void do_projectpaint_soften_f(ProjPaintState *ps,
4888                                      ProjPixel *projPixel,
4889                                      float mask,
4890                                      MemArena *softenArena,
4891                                      LinkNode **softenPixels)
4892 {
4893   float accum_tot = 0.0f;
4894   int xk, yk;
4895   BlurKernel *kernel = ps->blurkernel;
4896   float *rgba = projPixel->newColor.f;
4897 
4898   /* rather than painting, accumulate surrounding colors */
4899   zero_v4(rgba);
4900 
4901   for (yk = 0; yk < kernel->side; yk++) {
4902     for (xk = 0; xk < kernel->side; xk++) {
4903       float rgba_tmp[4];
4904       float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
4905 
4906       add_v2_v2(co_ofs, projPixel->projCoSS);
4907 
4908       if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
4909         float weight = kernel->wdata[xk + yk * kernel->side];
4910         mul_v4_fl(rgba_tmp, weight);
4911         add_v4_v4(rgba, rgba_tmp);
4912         accum_tot += weight;
4913       }
4914     }
4915   }
4916 
4917   if (LIKELY(accum_tot != 0)) {
4918     mul_v4_fl(rgba, 1.0f / (float)accum_tot);
4919 
4920     if (ps->mode == BRUSH_STROKE_INVERT) {
4921       /* subtract blurred image from normal image gives high pass filter */
4922       sub_v3_v3v3(rgba, projPixel->pixel.f_pt, rgba);
4923 
4924       /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
4925        * colored speckles appearing in final image, and also to check for threshold */
4926       rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
4927       if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
4928         float alpha = projPixel->pixel.f_pt[3];
4929         projPixel->pixel.f_pt[3] = rgba[3] = mask;
4930 
4931         /* add to enhance edges */
4932         blend_color_add_float(rgba, projPixel->pixel.f_pt, rgba);
4933         rgba[3] = alpha;
4934       }
4935       else {
4936         return;
4937       }
4938     }
4939     else {
4940       blend_color_interpolate_float(rgba, projPixel->pixel.f_pt, rgba, mask);
4941     }
4942 
4943     BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
4944   }
4945 }
4946 
do_projectpaint_soften(ProjPaintState * ps,ProjPixel * projPixel,float mask,MemArena * softenArena,LinkNode ** softenPixels)4947 static void do_projectpaint_soften(ProjPaintState *ps,
4948                                    ProjPixel *projPixel,
4949                                    float mask,
4950                                    MemArena *softenArena,
4951                                    LinkNode **softenPixels)
4952 {
4953   float accum_tot = 0;
4954   int xk, yk;
4955   BlurKernel *kernel = ps->blurkernel;
4956   /* convert to byte after */
4957   float rgba[4];
4958 
4959   /* rather than painting, accumulate surrounding colors */
4960   zero_v4(rgba);
4961 
4962   for (yk = 0; yk < kernel->side; yk++) {
4963     for (xk = 0; xk < kernel->side; xk++) {
4964       float rgba_tmp[4];
4965       float co_ofs[2] = {2.0f * xk - 1.0f, 2.0f * yk - 1.0f};
4966 
4967       add_v2_v2(co_ofs, projPixel->projCoSS);
4968 
4969       if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, true)) {
4970         float weight = kernel->wdata[xk + yk * kernel->side];
4971         mul_v4_fl(rgba_tmp, weight);
4972         add_v4_v4(rgba, rgba_tmp);
4973         accum_tot += weight;
4974       }
4975     }
4976   }
4977 
4978   if (LIKELY(accum_tot != 0)) {
4979     uchar *rgba_ub = projPixel->newColor.ch;
4980 
4981     mul_v4_fl(rgba, 1.0f / (float)accum_tot);
4982 
4983     if (ps->mode == BRUSH_STROKE_INVERT) {
4984       float rgba_pixel[4];
4985 
4986       straight_uchar_to_premul_float(rgba_pixel, projPixel->pixel.ch_pt);
4987 
4988       /* subtract blurred image from normal image gives high pass filter */
4989       sub_v3_v3v3(rgba, rgba_pixel, rgba);
4990       /* now rgba_ub contains the edge result, but this should be converted to luminance to avoid
4991        * colored speckles appearing in final image, and also to check for threshold */
4992       rgba[0] = rgba[1] = rgba[2] = IMB_colormanagement_get_luminance(rgba);
4993       if (fabsf(rgba[0]) > ps->brush->sharp_threshold) {
4994         float alpha = rgba_pixel[3];
4995         rgba[3] = rgba_pixel[3] = mask;
4996 
4997         /* add to enhance edges */
4998         blend_color_add_float(rgba, rgba_pixel, rgba);
4999 
5000         rgba[3] = alpha;
5001         premul_float_to_straight_uchar(rgba_ub, rgba);
5002       }
5003       else {
5004         return;
5005       }
5006     }
5007     else {
5008       premul_float_to_straight_uchar(rgba_ub, rgba);
5009       blend_color_interpolate_byte(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, mask);
5010     }
5011     BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena);
5012   }
5013 }
5014 
do_projectpaint_draw(ProjPaintState * ps,ProjPixel * projPixel,const float texrgb[3],float mask,float dither,float u,float v)5015 static void do_projectpaint_draw(ProjPaintState *ps,
5016                                  ProjPixel *projPixel,
5017                                  const float texrgb[3],
5018                                  float mask,
5019                                  float dither,
5020                                  float u,
5021                                  float v)
5022 {
5023   float rgb[3];
5024   uchar rgba_ub[4];
5025 
5026   if (ps->is_texbrush) {
5027     mul_v3_v3v3(rgb, texrgb, ps->paint_color_linear);
5028     /* TODO(sergey): Support texture paint color space. */
5029     if (ps->use_colormanagement) {
5030       linearrgb_to_srgb_v3_v3(rgb, rgb);
5031     }
5032     else {
5033       copy_v3_v3(rgb, rgb);
5034     }
5035   }
5036   else {
5037     copy_v3_v3(rgb, ps->paint_color);
5038   }
5039 
5040   if (dither > 0.0f) {
5041     float_to_byte_dither_v3(rgba_ub, rgb, dither, u, v);
5042   }
5043   else {
5044     unit_float_to_uchar_clamp_v3(rgba_ub, rgb);
5045   }
5046   rgba_ub[3] = f_to_char(mask);
5047 
5048   if (ps->do_masking) {
5049     IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
5050   }
5051   else {
5052     IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
5053   }
5054 }
5055 
do_projectpaint_draw_f(ProjPaintState * ps,ProjPixel * projPixel,const float texrgb[3],float mask)5056 static void do_projectpaint_draw_f(ProjPaintState *ps,
5057                                    ProjPixel *projPixel,
5058                                    const float texrgb[3],
5059                                    float mask)
5060 {
5061   float rgba[4];
5062 
5063   copy_v3_v3(rgba, ps->paint_color_linear);
5064 
5065   if (ps->is_texbrush) {
5066     mul_v3_v3(rgba, texrgb);
5067   }
5068 
5069   mul_v3_fl(rgba, mask);
5070   rgba[3] = mask;
5071 
5072   if (ps->do_masking) {
5073     IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
5074   }
5075   else {
5076     IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
5077   }
5078 }
5079 
do_projectpaint_mask(ProjPaintState * ps,ProjPixel * projPixel,float mask)5080 static void do_projectpaint_mask(ProjPaintState *ps, ProjPixel *projPixel, float mask)
5081 {
5082   uchar rgba_ub[4];
5083   rgba_ub[0] = rgba_ub[1] = rgba_ub[2] = ps->stencil_value * 255.0f;
5084   rgba_ub[3] = f_to_char(mask);
5085 
5086   if (ps->do_masking) {
5087     IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, rgba_ub, ps->blend);
5088   }
5089   else {
5090     IMB_blend_color_byte(projPixel->pixel.ch_pt, projPixel->pixel.ch_pt, rgba_ub, ps->blend);
5091   }
5092 }
5093 
do_projectpaint_mask_f(ProjPaintState * ps,ProjPixel * projPixel,float mask)5094 static void do_projectpaint_mask_f(ProjPaintState *ps, ProjPixel *projPixel, float mask)
5095 {
5096   float rgba[4];
5097   rgba[0] = rgba[1] = rgba[2] = ps->stencil_value;
5098   rgba[3] = mask;
5099 
5100   if (ps->do_masking) {
5101     IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->origColor.f_pt, rgba, ps->blend);
5102   }
5103   else {
5104     IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, ps->blend);
5105   }
5106 }
5107 
image_paint_partial_redraw_expand(ImagePaintPartialRedraw * cell,const ProjPixel * projPixel)5108 static void image_paint_partial_redraw_expand(ImagePaintPartialRedraw *cell,
5109                                               const ProjPixel *projPixel)
5110 {
5111   cell->x1 = min_ii(cell->x1, (int)projPixel->x_px);
5112   cell->y1 = min_ii(cell->y1, (int)projPixel->y_px);
5113 
5114   cell->x2 = max_ii(cell->x2, (int)projPixel->x_px + 1);
5115   cell->y2 = max_ii(cell->y2, (int)projPixel->y_px + 1);
5116 }
5117 
copy_original_alpha_channel(ProjPixel * pixel,bool is_floatbuf)5118 static void copy_original_alpha_channel(ProjPixel *pixel, bool is_floatbuf)
5119 {
5120   /* Use the original alpha channel data instead of the modified one */
5121   if (is_floatbuf) {
5122     /* slightly more involved case since floats are in premultiplied space we need
5123      * to make sure alpha is consistent, see T44627 */
5124     float rgb_straight[4];
5125     premul_to_straight_v4_v4(rgb_straight, pixel->pixel.f_pt);
5126     rgb_straight[3] = pixel->origColor.f_pt[3];
5127     straight_to_premul_v4_v4(pixel->pixel.f_pt, rgb_straight);
5128   }
5129   else {
5130     pixel->pixel.ch_pt[3] = pixel->origColor.ch_pt[3];
5131   }
5132 }
5133 
5134 /* Run this for single and multi-threaded painting. */
do_projectpaint_thread(TaskPool * __restrict UNUSED (pool),void * ph_v)5135 static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v)
5136 {
5137   /* First unpack args from the struct */
5138   ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps;
5139   ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages;
5140   const float *lastpos = ((ProjectHandle *)ph_v)->prevmval;
5141   const float *pos = ((ProjectHandle *)ph_v)->mval;
5142   const int thread_index = ((ProjectHandle *)ph_v)->thread_index;
5143   struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool;
5144   /* Done with args from ProjectHandle */
5145 
5146   LinkNode *node;
5147   ProjPixel *projPixel;
5148   Brush *brush = ps->brush;
5149 
5150   int last_index = -1;
5151   ProjPaintImage *last_projIma = NULL;
5152   ImagePaintPartialRedraw *last_partial_redraw_cell;
5153 
5154   float dist_sq, dist;
5155 
5156   float falloff;
5157   int bucket_index;
5158   bool is_floatbuf = false;
5159   const short tool = ps->tool;
5160   rctf bucket_bounds;
5161 
5162   /* for smear only */
5163   float pos_ofs[2] = {0};
5164   float co[2];
5165   ushort mask_short;
5166   const float brush_alpha = BKE_brush_alpha_get(ps->scene, brush);
5167   const float brush_radius = ps->brush_size;
5168   /* avoid a square root with every dist comparison */
5169   const float brush_radius_sq = brush_radius * brush_radius;
5170 
5171   const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ?
5172                               0 :
5173                               (brush->flag & BRUSH_LOCK_ALPHA) != 0;
5174 
5175   LinkNode *smearPixels = NULL;
5176   LinkNode *smearPixels_f = NULL;
5177   /* mem arena for this brush projection only */
5178   MemArena *smearArena = NULL;
5179 
5180   LinkNode *softenPixels = NULL;
5181   LinkNode *softenPixels_f = NULL;
5182   /* mem arena for this brush projection only */
5183   MemArena *softenArena = NULL;
5184 
5185   if (tool == PAINT_TOOL_SMEAR) {
5186     pos_ofs[0] = pos[0] - lastpos[0];
5187     pos_ofs[1] = pos[1] - lastpos[1];
5188 
5189     smearArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint smear arena");
5190   }
5191   else if (tool == PAINT_TOOL_SOFTEN) {
5192     softenArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint soften arena");
5193   }
5194 
5195   /* printf("brush bounds %d %d %d %d\n",
5196    *        bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
5197 
5198   while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {
5199 
5200     /* Check this bucket and its faces are initialized */
5201     if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
5202       rctf clip_rect = bucket_bounds;
5203       clip_rect.xmin -= PROJ_PIXEL_TOLERANCE;
5204       clip_rect.xmax += PROJ_PIXEL_TOLERANCE;
5205       clip_rect.ymin -= PROJ_PIXEL_TOLERANCE;
5206       clip_rect.ymax += PROJ_PIXEL_TOLERANCE;
5207       /* No pixels initialized */
5208       project_bucket_init(ps, thread_index, bucket_index, &clip_rect, &bucket_bounds);
5209     }
5210 
5211     if (ps->source != PROJ_SRC_VIEW) {
5212 
5213       /* Re-Projection, simple, no brushes! */
5214 
5215       for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
5216         projPixel = (ProjPixel *)node->link;
5217 
5218         /* copy of code below */
5219         if (last_index != projPixel->image_index) {
5220           last_index = projPixel->image_index;
5221           last_projIma = projImages + last_index;
5222 
5223           last_projIma->touch = 1;
5224           is_floatbuf = (last_projIma->ibuf->rect_float != NULL);
5225         }
5226         /* end copy */
5227 
5228         /* fill tools */
5229         if (ps->source == PROJ_SRC_VIEW_FILL) {
5230           if (brush->flag & BRUSH_USE_GRADIENT) {
5231             /* these could probably be cached instead of being done per pixel */
5232             float tangent[2];
5233             float line_len_sq_inv, line_len;
5234             float f;
5235             float color_f[4];
5236             const float p[2] = {
5237                 projPixel->projCoSS[0] - lastpos[0],
5238                 projPixel->projCoSS[1] - lastpos[1],
5239             };
5240 
5241             sub_v2_v2v2(tangent, pos, lastpos);
5242             line_len = len_squared_v2(tangent);
5243             line_len_sq_inv = 1.0f / line_len;
5244             line_len = sqrtf(line_len);
5245 
5246             switch (brush->gradient_fill_mode) {
5247               case BRUSH_GRADIENT_LINEAR: {
5248                 f = dot_v2v2(p, tangent) * line_len_sq_inv;
5249                 break;
5250               }
5251               case BRUSH_GRADIENT_RADIAL:
5252               default: {
5253                 f = len_v2(p) / line_len;
5254                 break;
5255               }
5256             }
5257             BKE_colorband_evaluate(brush->gradient, f, color_f);
5258             color_f[3] *= ((float)projPixel->mask) * (1.0f / 65535.0f) * brush_alpha;
5259 
5260             if (is_floatbuf) {
5261               /* convert to premultipied */
5262               mul_v3_fl(color_f, color_f[3]);
5263               IMB_blend_color_float(
5264                   projPixel->pixel.f_pt, projPixel->origColor.f_pt, color_f, ps->blend);
5265             }
5266             else {
5267               linearrgb_to_srgb_v3_v3(color_f, color_f);
5268 
5269               if (ps->dither > 0.0f) {
5270                 float_to_byte_dither_v3(
5271                     projPixel->newColor.ch, color_f, ps->dither, projPixel->x_px, projPixel->y_px);
5272               }
5273               else {
5274                 unit_float_to_uchar_clamp_v3(projPixel->newColor.ch, color_f);
5275               }
5276               projPixel->newColor.ch[3] = unit_float_to_uchar_clamp(color_f[3]);
5277               IMB_blend_color_byte(projPixel->pixel.ch_pt,
5278                                    projPixel->origColor.ch_pt,
5279                                    projPixel->newColor.ch,
5280                                    ps->blend);
5281             }
5282           }
5283           else {
5284             if (is_floatbuf) {
5285               float newColor_f[4];
5286               newColor_f[3] = ((float)projPixel->mask) * (1.0f / 65535.0f) * brush_alpha;
5287               copy_v3_v3(newColor_f, ps->paint_color_linear);
5288 
5289               IMB_blend_color_float(
5290                   projPixel->pixel.f_pt, projPixel->origColor.f_pt, newColor_f, ps->blend);
5291             }
5292             else {
5293               float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
5294               projPixel->newColor.ch[3] = mask * 255 * brush_alpha;
5295 
5296               rgb_float_to_uchar(projPixel->newColor.ch, ps->paint_color);
5297               IMB_blend_color_byte(projPixel->pixel.ch_pt,
5298                                    projPixel->origColor.ch_pt,
5299                                    projPixel->newColor.ch,
5300                                    ps->blend);
5301             }
5302           }
5303 
5304           if (lock_alpha) {
5305             copy_original_alpha_channel(projPixel, is_floatbuf);
5306           }
5307 
5308           last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
5309           image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
5310         }
5311         else {
5312           if (is_floatbuf) {
5313             BLI_assert(ps->reproject_ibuf->rect_float != NULL);
5314 
5315             bicubic_interpolation_color(ps->reproject_ibuf,
5316                                         NULL,
5317                                         projPixel->newColor.f,
5318                                         projPixel->projCoSS[0],
5319                                         projPixel->projCoSS[1]);
5320             if (projPixel->newColor.f[3]) {
5321               float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
5322 
5323               mul_v4_v4fl(projPixel->newColor.f, projPixel->newColor.f, mask);
5324 
5325               blend_color_mix_float(
5326                   projPixel->pixel.f_pt, projPixel->origColor.f_pt, projPixel->newColor.f);
5327             }
5328           }
5329           else {
5330             BLI_assert(ps->reproject_ibuf->rect != NULL);
5331 
5332             bicubic_interpolation_color(ps->reproject_ibuf,
5333                                         projPixel->newColor.ch,
5334                                         NULL,
5335                                         projPixel->projCoSS[0],
5336                                         projPixel->projCoSS[1]);
5337             if (projPixel->newColor.ch[3]) {
5338               float mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
5339               projPixel->newColor.ch[3] *= mask;
5340 
5341               blend_color_mix_byte(
5342                   projPixel->pixel.ch_pt, projPixel->origColor.ch_pt, projPixel->newColor.ch);
5343             }
5344           }
5345         }
5346       }
5347     }
5348     else {
5349       /* Normal brush painting */
5350 
5351       for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
5352 
5353         projPixel = (ProjPixel *)node->link;
5354 
5355         dist_sq = len_squared_v2v2(projPixel->projCoSS, pos);
5356 
5357         /*if (dist < radius) {*/ /* correct but uses a sqrtf */
5358         if (dist_sq <= brush_radius_sq) {
5359           dist = sqrtf(dist_sq);
5360 
5361           falloff = BKE_brush_curve_strength_clamped(ps->brush, dist, brush_radius);
5362 
5363           if (falloff > 0.0f) {
5364             float texrgb[3];
5365             float mask;
5366 
5367             /* Extra mask for normal, layer stencil, .. */
5368             float custom_mask = ((float)projPixel->mask) * (1.0f / 65535.0f);
5369 
5370             /* Mask texture. */
5371             if (ps->is_maskbrush) {
5372               float texmask = BKE_brush_sample_masktex(
5373                   ps->scene, ps->brush, projPixel->projCoSS, thread_index, pool);
5374               CLAMP(texmask, 0.0f, 1.0f);
5375               custom_mask *= texmask;
5376             }
5377 
5378             /* Color texture (alpha used as mask). */
5379             if (ps->is_texbrush) {
5380               MTex *mtex = &brush->mtex;
5381               float samplecos[3];
5382               float texrgba[4];
5383 
5384               /* taking 3d copy to account for 3D mapping too.
5385                * It gets concatenated during sampling */
5386               if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
5387                 copy_v3_v3(samplecos, projPixel->worldCoSS);
5388               }
5389               else {
5390                 copy_v2_v2(samplecos, projPixel->projCoSS);
5391                 samplecos[2] = 0.0f;
5392               }
5393 
5394               /* note, for clone and smear,
5395                * we only use the alpha, could be a special function */
5396               BKE_brush_sample_tex_3d(ps->scene, brush, samplecos, texrgba, thread_index, pool);
5397 
5398               copy_v3_v3(texrgb, texrgba);
5399               custom_mask *= texrgba[3];
5400             }
5401             else {
5402               zero_v3(texrgb);
5403             }
5404 
5405             if (ps->do_masking) {
5406               /* masking to keep brush contribution to a pixel limited. note we do not do
5407                * a simple max(mask, mask_accum), as this is very sensitive to spacing and
5408                * gives poor results for strokes crossing themselves.
5409                *
5410                * Instead we use a formula that adds up but approaches brush_alpha slowly
5411                * and never exceeds it, which gives nice smooth results. */
5412               float mask_accum = *projPixel->mask_accum;
5413               float max_mask = brush_alpha * custom_mask * falloff * 65535.0f;
5414 
5415               if (brush->flag & BRUSH_ACCUMULATE) {
5416                 mask = mask_accum + max_mask;
5417               }
5418               else {
5419                 mask = mask_accum + (max_mask - mask_accum * falloff);
5420               }
5421 
5422               mask = min_ff(mask, 65535.0f);
5423               mask_short = (ushort)mask;
5424 
5425               if (mask_short > *projPixel->mask_accum) {
5426                 *projPixel->mask_accum = mask_short;
5427                 mask = mask_short * (1.0f / 65535.0f);
5428               }
5429               else {
5430                 /* Go onto the next pixel */
5431                 continue;
5432               }
5433             }
5434             else {
5435               mask = brush_alpha * custom_mask * falloff;
5436             }
5437 
5438             if (mask > 0.0f) {
5439 
5440               /* copy of code above */
5441               if (last_index != projPixel->image_index) {
5442                 last_index = projPixel->image_index;
5443                 last_projIma = projImages + last_index;
5444 
5445                 last_projIma->touch = 1;
5446                 is_floatbuf = (last_projIma->ibuf->rect_float != NULL);
5447               }
5448               /* end copy */
5449 
5450               /* validate undo tile, since we will modify t*/
5451               *projPixel->valid = true;
5452 
5453               last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
5454               image_paint_partial_redraw_expand(last_partial_redraw_cell, projPixel);
5455 
5456               /* texrgb is not used for clone, smear or soften */
5457               switch (tool) {
5458                 case PAINT_TOOL_CLONE:
5459                   if (is_floatbuf) {
5460                     do_projectpaint_clone_f(ps, projPixel, mask);
5461                   }
5462                   else {
5463                     do_projectpaint_clone(ps, projPixel, mask);
5464                   }
5465                   break;
5466                 case PAINT_TOOL_SMEAR:
5467                   sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
5468 
5469                   if (is_floatbuf) {
5470                     do_projectpaint_smear_f(ps, projPixel, mask, smearArena, &smearPixels_f, co);
5471                   }
5472                   else {
5473                     do_projectpaint_smear(ps, projPixel, mask, smearArena, &smearPixels, co);
5474                   }
5475                   break;
5476                 case PAINT_TOOL_SOFTEN:
5477                   if (is_floatbuf) {
5478                     do_projectpaint_soften_f(ps, projPixel, mask, softenArena, &softenPixels_f);
5479                   }
5480                   else {
5481                     do_projectpaint_soften(ps, projPixel, mask, softenArena, &softenPixels);
5482                   }
5483                   break;
5484                 case PAINT_TOOL_MASK:
5485                   if (is_floatbuf) {
5486                     do_projectpaint_mask_f(ps, projPixel, mask);
5487                   }
5488                   else {
5489                     do_projectpaint_mask(ps, projPixel, mask);
5490                   }
5491                   break;
5492                 default:
5493                   if (is_floatbuf) {
5494                     do_projectpaint_draw_f(ps, projPixel, texrgb, mask);
5495                   }
5496                   else {
5497                     do_projectpaint_draw(
5498                         ps, projPixel, texrgb, mask, ps->dither, projPixel->x_px, projPixel->y_px);
5499                   }
5500                   break;
5501               }
5502 
5503               if (lock_alpha) {
5504                 copy_original_alpha_channel(projPixel, is_floatbuf);
5505               }
5506             }
5507 
5508             /* done painting */
5509           }
5510         }
5511       }
5512     }
5513   }
5514 
5515   if (tool == PAINT_TOOL_SMEAR) {
5516 
5517     for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */
5518       projPixel = node->link;
5519       *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
5520       if (lock_alpha) {
5521         copy_original_alpha_channel(projPixel, false);
5522       }
5523     }
5524 
5525     for (node = smearPixels_f; node; node = node->next) {
5526       projPixel = node->link;
5527       copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f);
5528       if (lock_alpha) {
5529         copy_original_alpha_channel(projPixel, true);
5530       }
5531     }
5532 
5533     BLI_memarena_free(smearArena);
5534   }
5535   else if (tool == PAINT_TOOL_SOFTEN) {
5536 
5537     for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */
5538       projPixel = node->link;
5539       *projPixel->pixel.uint_pt = projPixel->newColor.uint;
5540       if (lock_alpha) {
5541         copy_original_alpha_channel(projPixel, false);
5542       }
5543     }
5544 
5545     for (node = softenPixels_f; node; node = node->next) {
5546       projPixel = node->link;
5547       copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f);
5548       if (lock_alpha) {
5549         copy_original_alpha_channel(projPixel, true);
5550       }
5551     }
5552 
5553     BLI_memarena_free(softenArena);
5554   }
5555 }
5556 
project_paint_op(void * state,const float lastpos[2],const float pos[2])5557 static bool project_paint_op(void *state, const float lastpos[2], const float pos[2])
5558 {
5559   /* First unpack args from the struct */
5560   ProjPaintState *ps = (ProjPaintState *)state;
5561   bool touch_any = false;
5562 
5563   ProjectHandle handles[BLENDER_MAX_THREADS];
5564   TaskPool *task_pool = NULL;
5565   int a, i;
5566 
5567   struct ImagePool *image_pool;
5568 
5569   if (!project_bucket_iter_init(ps, pos)) {
5570     return touch_any;
5571   }
5572 
5573   if (ps->thread_tot > 1) {
5574     task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH);
5575   }
5576 
5577   image_pool = BKE_image_pool_new();
5578 
5579   if (!ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) {
5580     /* This means we are reprojecting an image, make sure the image has the needed data available.
5581      */
5582     bool float_dest = false;
5583     bool uchar_dest = false;
5584     /* Check if the destination images are float or uchar. */
5585     for (i = 0; i < ps->image_tot; i++) {
5586       if (ps->projImages[i].ibuf->rect != NULL) {
5587         uchar_dest = true;
5588       }
5589       if (ps->projImages[i].ibuf->rect_float != NULL) {
5590         float_dest = true;
5591       }
5592     }
5593 
5594     /* Generate missing data if needed. */
5595     if (float_dest && ps->reproject_ibuf->rect_float == NULL) {
5596       IMB_float_from_rect(ps->reproject_ibuf);
5597       ps->reproject_ibuf_free_float = true;
5598     }
5599     if (uchar_dest && ps->reproject_ibuf->rect == NULL) {
5600       IMB_rect_from_float(ps->reproject_ibuf);
5601       ps->reproject_ibuf_free_uchar = true;
5602     }
5603   }
5604 
5605   /* get the threads running */
5606   for (a = 0; a < ps->thread_tot; a++) {
5607 
5608     /* set defaults in handles */
5609     // memset(&handles[a], 0, sizeof(BakeShade));
5610 
5611     handles[a].ps = ps;
5612     copy_v2_v2(handles[a].mval, pos);
5613     copy_v2_v2(handles[a].prevmval, lastpos);
5614 
5615     /* thread specific */
5616     handles[a].thread_index = a;
5617 
5618     handles[a].projImages = BLI_memarena_alloc(ps->arena_mt[a],
5619                                                ps->image_tot * sizeof(ProjPaintImage));
5620 
5621     memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
5622 
5623     /* image bounds */
5624     for (i = 0; i < ps->image_tot; i++) {
5625       handles[a].projImages[i].partRedrawRect = BLI_memarena_alloc(
5626           ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
5627       memcpy(handles[a].projImages[i].partRedrawRect,
5628              ps->projImages[i].partRedrawRect,
5629              sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
5630     }
5631 
5632     handles[a].pool = image_pool;
5633 
5634     if (task_pool != NULL) {
5635       BLI_task_pool_push(task_pool, do_projectpaint_thread, &handles[a], false, NULL);
5636     }
5637   }
5638 
5639   if (task_pool != NULL) { /* wait for everything to be done */
5640     BLI_task_pool_work_and_wait(task_pool);
5641     BLI_task_pool_free(task_pool);
5642   }
5643   else {
5644     do_projectpaint_thread(NULL, &handles[0]);
5645   }
5646 
5647   BKE_image_pool_free(image_pool);
5648 
5649   /* move threaded bounds back into ps->projectPartialRedraws */
5650   for (i = 0; i < ps->image_tot; i++) {
5651     int touch = 0;
5652     for (a = 0; a < ps->thread_tot; a++) {
5653       touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect,
5654                                           handles[a].projImages[i].partRedrawRect,
5655                                           PROJ_BOUNDBOX_SQUARED);
5656     }
5657 
5658     if (touch) {
5659       ps->projImages[i].touch = 1;
5660       touch_any = 1;
5661     }
5662   }
5663 
5664   /* Calculate pivot for rotation around selection if needed. */
5665   if (U.uiflag & USER_ORBIT_SELECTION) {
5666     float w[3];
5667     int tri_index;
5668 
5669     tri_index = project_paint_PickFace(ps, pos, w);
5670 
5671     if (tri_index != -1) {
5672       const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
5673       const int lt_vtri[3] = {PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt)};
5674       float world[3];
5675       UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
5676 
5677       interp_v3_v3v3v3(world,
5678                        ps->mvert_eval[lt_vtri[0]].co,
5679                        ps->mvert_eval[lt_vtri[1]].co,
5680                        ps->mvert_eval[lt_vtri[2]].co,
5681                        w);
5682 
5683       ups->average_stroke_counter++;
5684       mul_m4_v3(ps->obmat, world);
5685       add_v3_v3(ups->average_stroke_accum, world);
5686       ups->last_stroke_valid = true;
5687     }
5688   }
5689 
5690   return touch_any;
5691 }
5692 
paint_proj_stroke_ps(const bContext * UNUSED (C),void * ps_handle_p,const float prev_pos[2],const float pos[2],const bool eraser,float pressure,float distance,float size,ProjPaintState * ps)5693 static void paint_proj_stroke_ps(const bContext *UNUSED(C),
5694                                  void *ps_handle_p,
5695                                  const float prev_pos[2],
5696                                  const float pos[2],
5697                                  const bool eraser,
5698                                  float pressure,
5699                                  float distance,
5700                                  float size,
5701                                  /* extra view */
5702                                  ProjPaintState *ps)
5703 {
5704   ProjStrokeHandle *ps_handle = ps_handle_p;
5705   Brush *brush = ps->brush;
5706   Scene *scene = ps->scene;
5707 
5708   ps->brush_size = size;
5709   ps->blend = brush->blend;
5710   if (eraser) {
5711     ps->blend = IMB_BLEND_ERASE_ALPHA;
5712   }
5713 
5714   /* handle gradient and inverted stroke color here */
5715   if (ELEM(ps->tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL)) {
5716     paint_brush_color_get(scene,
5717                           brush,
5718                           false,
5719                           ps->mode == BRUSH_STROKE_INVERT,
5720                           distance,
5721                           pressure,
5722                           ps->paint_color,
5723                           NULL);
5724     if (ps->use_colormanagement) {
5725       srgb_to_linearrgb_v3_v3(ps->paint_color_linear, ps->paint_color);
5726     }
5727     else {
5728       copy_v3_v3(ps->paint_color_linear, ps->paint_color);
5729     }
5730   }
5731   else if (ps->tool == PAINT_TOOL_MASK) {
5732     ps->stencil_value = brush->weight;
5733 
5734     if ((ps->mode == BRUSH_STROKE_INVERT) ^
5735         ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0)) {
5736       ps->stencil_value = 1.0f - ps->stencil_value;
5737     }
5738   }
5739 
5740   if (project_paint_op(ps, prev_pos, pos)) {
5741     ps_handle->need_redraw = true;
5742     project_image_refresh_tagged(ps);
5743   }
5744 }
5745 
paint_proj_stroke(const bContext * C,void * ps_handle_p,const float prev_pos[2],const float pos[2],const bool eraser,float pressure,float distance,float size)5746 void paint_proj_stroke(const bContext *C,
5747                        void *ps_handle_p,
5748                        const float prev_pos[2],
5749                        const float pos[2],
5750                        const bool eraser,
5751                        float pressure,
5752                        float distance,
5753                        float size)
5754 {
5755   int i;
5756   ProjStrokeHandle *ps_handle = ps_handle_p;
5757 
5758   /* clone gets special treatment here to avoid going through image initialization */
5759   if (ps_handle->is_clone_cursor_pick) {
5760     Scene *scene = ps_handle->scene;
5761     struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
5762     View3D *v3d = CTX_wm_view3d(C);
5763     ARegion *region = CTX_wm_region(C);
5764     float *cursor = scene->cursor.location;
5765     const int mval_i[2] = {(int)pos[0], (int)pos[1]};
5766 
5767     view3d_operator_needs_opengl(C);
5768 
5769     if (!ED_view3d_autodist(depsgraph, region, v3d, mval_i, cursor, false, NULL)) {
5770       return;
5771     }
5772 
5773     DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
5774     ED_region_tag_redraw(region);
5775 
5776     return;
5777   }
5778 
5779   for (i = 0; i < ps_handle->ps_views_tot; i++) {
5780     ProjPaintState *ps = ps_handle->ps_views[i];
5781     paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps);
5782   }
5783 }
5784 
5785 /* initialize project paint settings from context */
project_state_init(bContext * C,Object * ob,ProjPaintState * ps,int mode)5786 static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int mode)
5787 {
5788   Scene *scene = CTX_data_scene(C);
5789   ToolSettings *settings = scene->toolsettings;
5790 
5791   /* brush */
5792   ps->mode = mode;
5793   ps->brush = BKE_paint_brush(&settings->imapaint.paint);
5794   if (ps->brush) {
5795     Brush *brush = ps->brush;
5796     ps->tool = brush->imagepaint_tool;
5797     ps->blend = brush->blend;
5798     /* only check for inversion for the soften tool, elsewhere,
5799      * a resident brush inversion flag can cause issues */
5800     if (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
5801       ps->mode = (((ps->mode == BRUSH_STROKE_INVERT) ^ ((brush->flag & BRUSH_DIR_IN) != 0)) ?
5802                       BRUSH_STROKE_INVERT :
5803                       BRUSH_STROKE_NORMAL);
5804 
5805       ps->blurkernel = paint_new_blur_kernel(brush, true);
5806     }
5807 
5808     /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */
5809     ps->do_masking = paint_use_opacity_masking(brush);
5810     ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? true :
5811                                                                                        false;
5812     ps->is_maskbrush = (brush->mask_mtex.tex) ? true : false;
5813   }
5814   else {
5815     /* brush may be NULL*/
5816     ps->do_masking = false;
5817     ps->is_texbrush = false;
5818     ps->is_maskbrush = false;
5819   }
5820 
5821   /* sizeof(ProjPixel), since we alloc this a _lot_ */
5822   ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool);
5823   BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel));
5824 
5825   /* these can be NULL */
5826   ps->v3d = CTX_wm_view3d(C);
5827   ps->rv3d = CTX_wm_region_view3d(C);
5828   ps->region = CTX_wm_region(C);
5829 
5830   ps->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
5831   ps->scene = scene;
5832   /* allow override of active object */
5833   ps->ob = ob;
5834 
5835   ps->do_material_slots = (settings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
5836   ps->stencil_ima = settings->imapaint.stencil;
5837   ps->canvas_ima = (!ps->do_material_slots) ? settings->imapaint.canvas : NULL;
5838   ps->clone_ima = (!ps->do_material_slots) ? settings->imapaint.clone : NULL;
5839 
5840   ps->do_mask_cavity = (settings->imapaint.paint.flags & PAINT_USE_CAVITY_MASK) ? true : false;
5841   ps->cavity_curve = settings->imapaint.paint.cavity_curve;
5842 
5843   /* setup projection painting data */
5844   if (ps->tool != PAINT_TOOL_FILL) {
5845     ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? false : true;
5846     ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? false : true;
5847     ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? false : true;
5848   }
5849   else {
5850     ps->do_backfacecull = ps->do_occlude = ps->do_mask_normal = 0;
5851   }
5852 
5853   if (ps->tool == PAINT_TOOL_CLONE) {
5854     ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) ? 1 : 0;
5855   }
5856 
5857   ps->do_stencil_brush = (ps->brush && ps->brush->imagepaint_tool == PAINT_TOOL_MASK);
5858   /* deactivate stenciling for the stencil brush :) */
5859   ps->do_layer_stencil = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) &&
5860                           !(ps->do_stencil_brush) && ps->stencil_ima);
5861   ps->do_layer_stencil_inv = ((settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) !=
5862                               0);
5863 
5864 #ifndef PROJ_DEBUG_NOSEAMBLEED
5865   /* pixel num to bleed */
5866   ps->seam_bleed_px = settings->imapaint.seam_bleed;
5867   ps->seam_bleed_px_sq = square_s(settings->imapaint.seam_bleed);
5868 #endif
5869 
5870   if (ps->do_mask_normal) {
5871     ps->normal_angle_inner = settings->imapaint.normal_angle;
5872     ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f;
5873   }
5874   else {
5875     ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle;
5876   }
5877 
5878   ps->normal_angle_inner *= (float)(M_PI_2 / 90);
5879   ps->normal_angle *= (float)(M_PI_2 / 90);
5880   ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
5881 
5882   if (ps->normal_angle_range <= 0.0f) {
5883     /* no need to do blending */
5884     ps->do_mask_normal = false;
5885   }
5886 
5887   ps->normal_angle__cos = cosf(ps->normal_angle);
5888   ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner);
5889 
5890   ps->dither = settings->imapaint.dither;
5891 
5892   ps->use_colormanagement = BKE_scene_check_color_management_enabled(CTX_data_scene(C));
5893 }
5894 
paint_proj_new_stroke(bContext * C,Object * ob,const float mouse[2],int mode)5895 void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode)
5896 {
5897   ProjStrokeHandle *ps_handle;
5898   Scene *scene = CTX_data_scene(C);
5899   ToolSettings *settings = scene->toolsettings;
5900   char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0};
5901 
5902   ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle");
5903   ps_handle->scene = scene;
5904   ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint);
5905 
5906   /* bypass regular stroke logic */
5907   if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) && (mode == BRUSH_STROKE_INVERT)) {
5908     view3d_operator_needs_opengl(C);
5909     ps_handle->is_clone_cursor_pick = true;
5910     return ps_handle;
5911   }
5912 
5913   ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush);
5914 
5915   Mesh *mesh = BKE_mesh_from_object(ob);
5916   ps_handle->symmetry_flags = mesh->symmetry;
5917   ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1);
5918   bool is_multi_view = (ps_handle->ps_views_tot != 1);
5919 
5920   for (int i = 0; i < ps_handle->ps_views_tot; i++) {
5921     ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState");
5922     ps_handle->ps_views[i] = ps;
5923   }
5924 
5925   if (ps_handle->symmetry_flags) {
5926     int index = 0;
5927 
5928     int x = 0;
5929     do {
5930       int y = 0;
5931       do {
5932         int z = 0;
5933         do {
5934           symmetry_flag_views[index++] = ((x ? PAINT_SYMM_X : 0) | (y ? PAINT_SYMM_Y : 0) |
5935                                           (z ? PAINT_SYMM_Z : 0));
5936           BLI_assert(index <= ps_handle->ps_views_tot);
5937         } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z));
5938       } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y));
5939     } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X));
5940     BLI_assert(index == ps_handle->ps_views_tot);
5941   }
5942 
5943   for (int i = 0; i < ps_handle->ps_views_tot; i++) {
5944     ProjPaintState *ps = ps_handle->ps_views[i];
5945 
5946     project_state_init(C, ob, ps, mode);
5947 
5948     if (ps->ob == NULL) {
5949       ps_handle->ps_views_tot = i + 1;
5950       goto fail;
5951     }
5952   }
5953 
5954   /* Don't allow brush size below 2 */
5955   if (BKE_brush_size_get(scene, ps_handle->brush) < 2) {
5956     BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize);
5957   }
5958 
5959   /* allocate and initialize spatial data structures */
5960 
5961   for (int i = 0; i < ps_handle->ps_views_tot; i++) {
5962     ProjPaintState *ps = ps_handle->ps_views[i];
5963 
5964     ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW;
5965     project_image_refresh_tagged(ps);
5966 
5967     /* re-use! */
5968     if (i != 0) {
5969       ps->is_shared_user = true;
5970       PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]);
5971     }
5972 
5973     project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
5974     if (ps->me_eval == NULL) {
5975       goto fail;
5976     }
5977 
5978     paint_proj_begin_clone(ps, mouse);
5979   }
5980 
5981   paint_brush_init_tex(ps_handle->brush);
5982 
5983   return ps_handle;
5984 
5985 fail:
5986   for (int i = 0; i < ps_handle->ps_views_tot; i++) {
5987     ProjPaintState *ps = ps_handle->ps_views[i];
5988     MEM_freeN(ps);
5989   }
5990   MEM_freeN(ps_handle);
5991   return NULL;
5992 }
5993 
paint_proj_redraw(const bContext * C,void * ps_handle_p,bool final)5994 void paint_proj_redraw(const bContext *C, void *ps_handle_p, bool final)
5995 {
5996   ProjStrokeHandle *ps_handle = ps_handle_p;
5997 
5998   if (ps_handle->need_redraw) {
5999     ps_handle->need_redraw = false;
6000   }
6001   else if (!final) {
6002     return;
6003   }
6004 
6005   if (final) {
6006     /* compositor listener deals with updating */
6007     WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL);
6008   }
6009   else {
6010     ED_region_tag_redraw(CTX_wm_region(C));
6011   }
6012 }
6013 
paint_proj_stroke_done(void * ps_handle_p)6014 void paint_proj_stroke_done(void *ps_handle_p)
6015 {
6016   ProjStrokeHandle *ps_handle = ps_handle_p;
6017   Scene *scene = ps_handle->scene;
6018 
6019   if (ps_handle->is_clone_cursor_pick) {
6020     MEM_freeN(ps_handle);
6021     return;
6022   }
6023 
6024   for (int i = 1; i < ps_handle->ps_views_tot; i++) {
6025     PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]);
6026   }
6027 
6028   BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size);
6029 
6030   paint_brush_exit_tex(ps_handle->brush);
6031 
6032   for (int i = 0; i < ps_handle->ps_views_tot; i++) {
6033     ProjPaintState *ps;
6034     ps = ps_handle->ps_views[i];
6035     project_paint_end(ps);
6036     MEM_freeN(ps);
6037   }
6038 
6039   MEM_freeN(ps_handle);
6040 }
6041 /* use project paint to re-apply an image */
texture_paint_camera_project_exec(bContext * C,wmOperator * op)6042 static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
6043 {
6044   Main *bmain = CTX_data_main(C);
6045   Image *image = BLI_findlink(&bmain->images, RNA_enum_get(op->ptr, "image"));
6046   Scene *scene = CTX_data_scene(C);
6047   ViewLayer *view_layer = CTX_data_view_layer(C);
6048   ProjPaintState ps = {NULL};
6049   int orig_brush_size;
6050   IDProperty *idgroup;
6051   IDProperty *view_data = NULL;
6052   Object *ob = OBACT(view_layer);
6053   bool uvs, mat, tex;
6054 
6055   if (ob == NULL || ob->type != OB_MESH) {
6056     BKE_report(op->reports, RPT_ERROR, "No active mesh object");
6057     return OPERATOR_CANCELLED;
6058   }
6059 
6060   if (!ED_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, NULL)) {
6061     ED_paint_data_warning(op->reports, uvs, mat, tex, true);
6062     WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
6063     return OPERATOR_CANCELLED;
6064   }
6065 
6066   project_state_init(C, ob, &ps, BRUSH_STROKE_NORMAL);
6067 
6068   if (image == NULL) {
6069     BKE_report(op->reports, RPT_ERROR, "Image could not be found");
6070     return OPERATOR_CANCELLED;
6071   }
6072 
6073   ps.reproject_image = image;
6074   ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
6075 
6076   if ((ps.reproject_ibuf == NULL) ||
6077       ((ps.reproject_ibuf->rect || ps.reproject_ibuf->rect_float) == false)) {
6078     BKE_report(op->reports, RPT_ERROR, "Image data could not be found");
6079     return OPERATOR_CANCELLED;
6080   }
6081 
6082   idgroup = IDP_GetProperties(&image->id, 0);
6083 
6084   if (idgroup) {
6085     view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY);
6086 
6087     /* type check to make sure its ok */
6088     if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) {
6089       BKE_report(op->reports, RPT_ERROR, "Image project data invalid");
6090       return OPERATOR_CANCELLED;
6091     }
6092   }
6093 
6094   if (view_data) {
6095     /* image has stored view projection info */
6096     ps.source = PROJ_SRC_IMAGE_VIEW;
6097   }
6098   else {
6099     ps.source = PROJ_SRC_IMAGE_CAM;
6100 
6101     if (scene->camera == NULL) {
6102       BKE_report(op->reports, RPT_ERROR, "No active camera set");
6103       return OPERATOR_CANCELLED;
6104     }
6105   }
6106 
6107   /* override */
6108   ps.is_texbrush = false;
6109   ps.is_maskbrush = false;
6110   ps.do_masking = false;
6111   orig_brush_size = BKE_brush_size_get(scene, ps.brush);
6112   /* cover the whole image */
6113   BKE_brush_size_set(scene, ps.brush, 32 * U.pixelsize);
6114 
6115   /* so pixels are initialized with minimal info */
6116   ps.tool = PAINT_TOOL_DRAW;
6117 
6118   scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
6119 
6120   /* allocate and initialize spatial data structures */
6121   project_paint_begin(C, &ps, false, 0);
6122 
6123   if (ps.me_eval == NULL) {
6124     BKE_brush_size_set(scene, ps.brush, orig_brush_size);
6125     BKE_report(op->reports, RPT_ERROR, "Could not get valid evaluated mesh");
6126     return OPERATOR_CANCELLED;
6127   }
6128 
6129   ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
6130 
6131   const float pos[2] = {0.0, 0.0};
6132   const float lastpos[2] = {0.0, 0.0};
6133   int a;
6134 
6135   project_paint_op(&ps, lastpos, pos);
6136 
6137   project_image_refresh_tagged(&ps);
6138 
6139   for (a = 0; a < ps.image_tot; a++) {
6140     BKE_image_free_gputextures(ps.projImages[a].ima);
6141     WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima);
6142   }
6143 
6144   project_paint_end(&ps);
6145 
6146   ED_image_undo_push_end();
6147 
6148   scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
6149   BKE_brush_size_set(scene, ps.brush, orig_brush_size);
6150 
6151   return OPERATOR_FINISHED;
6152 }
6153 
PAINT_OT_project_image(wmOperatorType * ot)6154 void PAINT_OT_project_image(wmOperatorType *ot)
6155 {
6156   PropertyRNA *prop;
6157 
6158   /* identifiers */
6159   ot->name = "Project Image";
6160   ot->idname = "PAINT_OT_project_image";
6161   ot->description = "Project an edited render from the active camera back onto the object";
6162 
6163   /* api callbacks */
6164   ot->invoke = WM_enum_search_invoke;
6165   ot->exec = texture_paint_camera_project_exec;
6166 
6167   /* flags */
6168   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
6169 
6170   prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", "");
6171   RNA_def_enum_funcs(prop, RNA_image_itemf);
6172   RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
6173   ot->prop = prop;
6174 }
6175 
texture_paint_image_from_view_poll(bContext * C)6176 static bool texture_paint_image_from_view_poll(bContext *C)
6177 {
6178   bScreen *screen = CTX_wm_screen(C);
6179   if (!(screen && BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0))) {
6180     CTX_wm_operator_poll_msg_set(C, "No 3D viewport found to create image from");
6181     return false;
6182   }
6183   if (G.background || !GPU_is_init()) {
6184     return false;
6185   }
6186   return true;
6187 }
6188 
texture_paint_image_from_view_exec(bContext * C,wmOperator * op)6189 static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
6190 {
6191   Image *image;
6192   ImBuf *ibuf;
6193   char filename[FILE_MAX];
6194 
6195   Main *bmain = CTX_data_main(C);
6196   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
6197   Scene *scene = CTX_data_scene(C);
6198   ToolSettings *settings = scene->toolsettings;
6199   int w = settings->imapaint.screen_grab_size[0];
6200   int h = settings->imapaint.screen_grab_size[1];
6201   int maxsize;
6202   char err_out[256] = "unknown";
6203 
6204   ScrArea *area = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0);
6205   if (!area) {
6206     BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
6207     return OPERATOR_CANCELLED;
6208   }
6209 
6210   ARegion *region = BKE_area_find_region_active_win(area);
6211   if (!region) {
6212     BKE_report(op->reports, RPT_ERROR, "No 3D viewport found to create image from");
6213     return OPERATOR_CANCELLED;
6214   }
6215   RegionView3D *rv3d = region->regiondata;
6216 
6217   RNA_string_get(op->ptr, "filepath", filename);
6218 
6219   maxsize = GPU_max_texture_size();
6220 
6221   if (w > maxsize) {
6222     w = maxsize;
6223   }
6224   if (h > maxsize) {
6225     h = maxsize;
6226   }
6227 
6228   /* Create a copy of the overlays where they are all turned off, except the
6229    * texture paint overlay opacity */
6230   View3D *v3d = area->spacedata.first;
6231   View3D v3d_copy = *v3d;
6232   v3d_copy.gridflag = 0;
6233   v3d_copy.flag2 = 0;
6234   v3d_copy.flag = V3D_HIDE_HELPLINES;
6235   v3d_copy.gizmo_flag = V3D_GIZMO_HIDE;
6236 
6237   memset(&v3d_copy.overlay, 0, sizeof(View3DOverlay));
6238   v3d_copy.overlay.flag = V3D_OVERLAY_HIDE_CURSOR | V3D_OVERLAY_HIDE_TEXT |
6239                           V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_BONES |
6240                           V3D_OVERLAY_HIDE_OBJECT_XTRAS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
6241   v3d_copy.overlay.texture_paint_mode_opacity = v3d->overlay.texture_paint_mode_opacity;
6242 
6243   ibuf = ED_view3d_draw_offscreen_imbuf(depsgraph,
6244                                         scene,
6245                                         v3d_copy.shading.type,
6246                                         &v3d_copy,
6247                                         region,
6248                                         w,
6249                                         h,
6250                                         IB_rect,
6251                                         R_ALPHAPREMUL,
6252                                         NULL,
6253                                         NULL,
6254                                         err_out);
6255 
6256   if (!ibuf) {
6257     /* Mostly happens when OpenGL offscreen buffer was failed to create, */
6258     /* but could be other reasons. Should be handled in the future. nazgul */
6259     BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out);
6260     return OPERATOR_CANCELLED;
6261   }
6262 
6263   image = BKE_image_add_from_imbuf(bmain, ibuf, "image_view");
6264 
6265   /* Drop reference to ibuf so that the image owns it */
6266   IMB_freeImBuf(ibuf);
6267 
6268   if (image) {
6269     /* now for the trickiness. store the view projection here!
6270      * re-projection will reuse this */
6271     IDPropertyTemplate val;
6272     IDProperty *idgroup = IDP_GetProperties(&image->id, 1);
6273     IDProperty *view_data;
6274     bool is_ortho;
6275     float *array;
6276 
6277     val.array.len = PROJ_VIEW_DATA_SIZE;
6278     val.array.type = IDP_FLOAT;
6279     view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID);
6280 
6281     array = (float *)IDP_Array(view_data);
6282     memcpy(array, rv3d->winmat, sizeof(rv3d->winmat));
6283     array += sizeof(rv3d->winmat) / sizeof(float);
6284     memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat));
6285     array += sizeof(rv3d->viewmat) / sizeof(float);
6286     is_ortho = ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &array[0], &array[1], true);
6287     /* using float for a bool is dodgy but since its an extra member in the array...
6288      * easier than adding a single bool prop */
6289     array[2] = is_ortho ? 1.0f : 0.0f;
6290 
6291     IDP_AddToGroup(idgroup, view_data);
6292   }
6293 
6294   return OPERATOR_FINISHED;
6295 }
6296 
PAINT_OT_image_from_view(wmOperatorType * ot)6297 void PAINT_OT_image_from_view(wmOperatorType *ot)
6298 {
6299   /* identifiers */
6300   ot->name = "Image from View";
6301   ot->idname = "PAINT_OT_image_from_view";
6302   ot->description = "Make an image from biggest 3D view for re-projection";
6303 
6304   /* api callbacks */
6305   ot->exec = texture_paint_image_from_view_exec;
6306   ot->poll = texture_paint_image_from_view_poll;
6307 
6308   /* flags */
6309   ot->flag = OPTYPE_REGISTER;
6310 
6311   RNA_def_string_file_name(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Name of the file");
6312 }
6313 
6314 /*********************************************
6315  * Data generation for projective texturing  *
6316  * *******************************************/
6317 
ED_paint_data_warning(struct ReportList * reports,bool uvs,bool mat,bool tex,bool stencil)6318 void ED_paint_data_warning(struct ReportList *reports, bool uvs, bool mat, bool tex, bool stencil)
6319 {
6320   BKE_reportf(reports,
6321               RPT_WARNING,
6322               "Missing%s%s%s%s detected!",
6323               !uvs ? " UVs," : "",
6324               !mat ? " Materials," : "",
6325               !tex ? " Textures," : "",
6326               !stencil ? " Stencil," : "");
6327 }
6328 
6329 /* Make sure that active object has a material,
6330  * and assign UVs and image layers if they do not exist */
ED_paint_proj_mesh_data_check(Scene * scene,Object * ob,bool * uvs,bool * mat,bool * tex,bool * stencil)6331 bool ED_paint_proj_mesh_data_check(
6332     Scene *scene, Object *ob, bool *uvs, bool *mat, bool *tex, bool *stencil)
6333 {
6334   Mesh *me;
6335   int layernum;
6336   ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
6337   Brush *br = BKE_paint_brush(&imapaint->paint);
6338   bool hasmat = true;
6339   bool hastex = true;
6340   bool hasstencil = true;
6341   bool hasuvs = true;
6342 
6343   imapaint->missing_data = 0;
6344 
6345   BLI_assert(ob->type == OB_MESH);
6346 
6347   if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
6348     /* no material, add one */
6349     if (ob->totcol == 0) {
6350       hasmat = false;
6351       hastex = false;
6352     }
6353     else {
6354       /* there may be material slots but they may be empty, check */
6355       hasmat = false;
6356       hastex = false;
6357 
6358       for (int i = 1; i < ob->totcol + 1; i++) {
6359         Material *ma = BKE_object_material_get(ob, i);
6360 
6361         if (ma && !ID_IS_LINKED(ma)) {
6362           hasmat = true;
6363           if (ma->texpaintslot == NULL) {
6364             /* refresh here just in case */
6365             BKE_texpaint_slot_refresh_cache(scene, ma);
6366           }
6367           if (ma->texpaintslot != NULL &&
6368               (ma->texpaintslot[ma->paint_active_slot].ima == NULL ||
6369                !ID_IS_LINKED(ma->texpaintslot[ma->paint_active_slot].ima))) {
6370             hastex = true;
6371             break;
6372           }
6373         }
6374       }
6375     }
6376   }
6377   else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
6378     if (imapaint->canvas == NULL || ID_IS_LINKED(imapaint->canvas)) {
6379       hastex = false;
6380     }
6381   }
6382 
6383   me = BKE_mesh_from_object(ob);
6384   layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
6385 
6386   if (layernum == 0) {
6387     hasuvs = false;
6388   }
6389 
6390   /* Make sure we have a stencil to paint on! */
6391   if (br && br->imagepaint_tool == PAINT_TOOL_MASK) {
6392     imapaint->flag |= IMAGEPAINT_PROJECT_LAYER_STENCIL;
6393 
6394     if (imapaint->stencil == NULL) {
6395       hasstencil = false;
6396     }
6397   }
6398 
6399   if (!hasuvs) {
6400     imapaint->missing_data |= IMAGEPAINT_MISSING_UVS;
6401   }
6402   if (!hasmat) {
6403     imapaint->missing_data |= IMAGEPAINT_MISSING_MATERIAL;
6404   }
6405   if (!hastex) {
6406     imapaint->missing_data |= IMAGEPAINT_MISSING_TEX;
6407   }
6408   if (!hasstencil) {
6409     imapaint->missing_data |= IMAGEPAINT_MISSING_STENCIL;
6410   }
6411 
6412   if (uvs) {
6413     *uvs = hasuvs;
6414   }
6415   if (mat) {
6416     *mat = hasmat;
6417   }
6418   if (tex) {
6419     *tex = hastex;
6420   }
6421   if (stencil) {
6422     *stencil = hasstencil;
6423   }
6424 
6425   return hasuvs && hasmat && hastex && hasstencil;
6426 }
6427 
6428 /* Add layer operator */
6429 enum {
6430   LAYER_BASE_COLOR,
6431   LAYER_SPECULAR,
6432   LAYER_ROUGHNESS,
6433   LAYER_METALLIC,
6434   LAYER_NORMAL,
6435   LAYER_BUMP,
6436   LAYER_DISPLACEMENT,
6437 };
6438 
6439 static const EnumPropertyItem layer_type_items[] = {
6440     {LAYER_BASE_COLOR, "BASE_COLOR", 0, "Base Color", ""},
6441     {LAYER_SPECULAR, "SPECULAR", 0, "Specular", ""},
6442     {LAYER_ROUGHNESS, "ROUGHNESS", 0, "Roughness", ""},
6443     {LAYER_METALLIC, "METALLIC", 0, "Metallic", ""},
6444     {LAYER_NORMAL, "NORMAL", 0, "Normal", ""},
6445     {LAYER_BUMP, "BUMP", 0, "Bump", ""},
6446     {LAYER_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", ""},
6447     {0, NULL, 0, NULL, NULL},
6448 };
6449 
proj_paint_image_create(wmOperator * op,Main * bmain,bool is_data)6450 static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data)
6451 {
6452   Image *ima;
6453   float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
6454   char imagename[MAX_ID_NAME - 2] = "Material Diffuse Color";
6455   int width = 1024;
6456   int height = 1024;
6457   bool use_float = false;
6458   short gen_type = IMA_GENTYPE_BLANK;
6459   bool alpha = false;
6460 
6461   if (op) {
6462     width = RNA_int_get(op->ptr, "width");
6463     height = RNA_int_get(op->ptr, "height");
6464     use_float = RNA_boolean_get(op->ptr, "float");
6465     gen_type = RNA_enum_get(op->ptr, "generated_type");
6466     RNA_float_get_array(op->ptr, "color", color);
6467     alpha = RNA_boolean_get(op->ptr, "alpha");
6468     RNA_string_get(op->ptr, "name", imagename);
6469   }
6470   ima = BKE_image_add_generated(bmain,
6471                                 width,
6472                                 height,
6473                                 imagename,
6474                                 alpha ? 32 : 24,
6475                                 use_float,
6476                                 gen_type,
6477                                 color,
6478                                 false,
6479                                 is_data,
6480                                 false); /* TODO(lukas): Add option */
6481 
6482   return ima;
6483 }
6484 
proj_paint_default_color(wmOperator * op,int type,Material * ma)6485 static void proj_paint_default_color(wmOperator *op, int type, Material *ma)
6486 {
6487   if (RNA_struct_property_is_set(op->ptr, "color")) {
6488     return;
6489   }
6490 
6491   bNode *in_node = ntreeFindType(ma->nodetree, SH_NODE_BSDF_PRINCIPLED);
6492   if (in_node == NULL) {
6493     return;
6494   }
6495 
6496   float color[4];
6497 
6498   if (type >= LAYER_BASE_COLOR && type < LAYER_NORMAL) {
6499     /* Copy color from node, so result is unchanged after assigning textures. */
6500     bNodeSocket *in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
6501 
6502     switch (in_sock->type) {
6503       case SOCK_FLOAT: {
6504         bNodeSocketValueFloat *socket_data = in_sock->default_value;
6505         copy_v3_fl(color, socket_data->value);
6506         color[3] = 1.0f;
6507         break;
6508       }
6509       case SOCK_VECTOR:
6510       case SOCK_RGBA: {
6511         bNodeSocketValueRGBA *socket_data = in_sock->default_value;
6512         copy_v3_v3(color, socket_data->value);
6513         color[3] = 1.0f;
6514         break;
6515       }
6516       default: {
6517         return;
6518       }
6519     }
6520   }
6521   else if (type == LAYER_NORMAL) {
6522     /* Neutral tangent space normal map. */
6523     rgba_float_args_set(color, 0.5f, 0.5f, 1.0f, 1.0f);
6524   }
6525   else if (ELEM(type, LAYER_BUMP, LAYER_DISPLACEMENT)) {
6526     /* Neutral displacement and bump map. */
6527     rgba_float_args_set(color, 0.5f, 0.5f, 0.5f, 1.0f);
6528   }
6529   else {
6530     return;
6531   }
6532 
6533   RNA_float_set_array(op->ptr, "color", color);
6534 }
6535 
proj_paint_add_slot(bContext * C,wmOperator * op)6536 static bool proj_paint_add_slot(bContext *C, wmOperator *op)
6537 {
6538   Object *ob = ED_object_active_context(C);
6539   Scene *scene = CTX_data_scene(C);
6540   Material *ma;
6541   Image *ima = NULL;
6542 
6543   if (!ob) {
6544     return false;
6545   }
6546 
6547   ma = BKE_object_material_get(ob, ob->actcol);
6548 
6549   if (ma) {
6550     Main *bmain = CTX_data_main(C);
6551     int type = RNA_enum_get(op->ptr, "type");
6552     bool is_data = (type > LAYER_BASE_COLOR);
6553 
6554     bNode *imanode;
6555     bNodeTree *ntree = ma->nodetree;
6556 
6557     if (!ntree) {
6558       ED_node_shader_default(C, &ma->id);
6559       ntree = ma->nodetree;
6560     }
6561 
6562     ma->use_nodes = true;
6563 
6564     /* try to add an image node */
6565     imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
6566 
6567     ima = proj_paint_image_create(op, bmain, is_data);
6568     imanode->id = &ima->id;
6569 
6570     nodeSetActive(ntree, imanode);
6571 
6572     /* Connect to first available principled bsdf node. */
6573     bNode *in_node = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
6574     bNode *out_node = imanode;
6575 
6576     if (in_node != NULL) {
6577       bNodeSocket *out_sock = nodeFindSocket(out_node, SOCK_OUT, "Color");
6578       bNodeSocket *in_sock = NULL;
6579 
6580       if (type >= LAYER_BASE_COLOR && type < LAYER_NORMAL) {
6581         in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
6582       }
6583       else if (type == LAYER_NORMAL) {
6584         bNode *nor_node;
6585         nor_node = nodeAddStaticNode(C, ntree, SH_NODE_NORMAL_MAP);
6586 
6587         in_sock = nodeFindSocket(nor_node, SOCK_IN, "Color");
6588         nodeAddLink(ntree, out_node, out_sock, nor_node, in_sock);
6589 
6590         in_sock = nodeFindSocket(in_node, SOCK_IN, "Normal");
6591         out_sock = nodeFindSocket(nor_node, SOCK_OUT, "Normal");
6592 
6593         out_node = nor_node;
6594       }
6595       else if (type == LAYER_BUMP) {
6596         bNode *bump_node;
6597         bump_node = nodeAddStaticNode(C, ntree, SH_NODE_BUMP);
6598 
6599         in_sock = nodeFindSocket(bump_node, SOCK_IN, "Height");
6600         nodeAddLink(ntree, out_node, out_sock, bump_node, in_sock);
6601 
6602         in_sock = nodeFindSocket(in_node, SOCK_IN, "Normal");
6603         out_sock = nodeFindSocket(bump_node, SOCK_OUT, "Normal");
6604 
6605         out_node = bump_node;
6606       }
6607       else if (type == LAYER_DISPLACEMENT) {
6608         /* Connect to the displacement output socket */
6609         in_node = ntreeFindType(ntree, SH_NODE_OUTPUT_MATERIAL);
6610 
6611         if (in_node != NULL) {
6612           in_sock = nodeFindSocket(in_node, SOCK_IN, layer_type_items[type].name);
6613         }
6614         else {
6615           in_sock = NULL;
6616         }
6617       }
6618 
6619       /* Check if the socket in already connected to something */
6620       bNodeLink *link = in_sock ? in_sock->link : NULL;
6621       if (in_sock != NULL && link == NULL) {
6622         nodeAddLink(ntree, out_node, out_sock, in_node, in_sock);
6623 
6624         nodePositionRelative(out_node, in_node, out_sock, in_sock);
6625       }
6626     }
6627 
6628     ntreeUpdateTree(CTX_data_main(C), ntree);
6629     /* In case we added more than one node, position them too. */
6630     nodePositionPropagate(out_node);
6631 
6632     if (ima) {
6633       BKE_texpaint_slot_refresh_cache(scene, ma);
6634       BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
6635       WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
6636     }
6637 
6638     DEG_id_tag_update(&ntree->id, 0);
6639     DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
6640     ED_area_tag_redraw(CTX_wm_area(C));
6641 
6642     ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
6643 
6644     return true;
6645   }
6646 
6647   return false;
6648 }
6649 
get_texture_layer_type(wmOperator * op,const char * prop_name)6650 static int get_texture_layer_type(wmOperator *op, const char *prop_name)
6651 {
6652   int type_value = RNA_enum_get(op->ptr, prop_name);
6653   int type = RNA_enum_from_value(layer_type_items, type_value);
6654   BLI_assert(type != -1);
6655   return type;
6656 }
6657 
get_or_create_current_material(bContext * C,Object * ob)6658 static Material *get_or_create_current_material(bContext *C, Object *ob)
6659 {
6660   Material *ma = BKE_object_material_get(ob, ob->actcol);
6661   if (!ma) {
6662     Main *bmain = CTX_data_main(C);
6663     ma = BKE_material_add(bmain, "Material");
6664     BKE_object_material_assign(bmain, ob, ma, ob->actcol, BKE_MAT_ASSIGN_USERPREF);
6665   }
6666   return ma;
6667 }
6668 
texture_paint_add_texture_paint_slot_exec(bContext * C,wmOperator * op)6669 static int texture_paint_add_texture_paint_slot_exec(bContext *C, wmOperator *op)
6670 {
6671   Object *ob = ED_object_active_context(C);
6672   Material *ma = get_or_create_current_material(C, ob);
6673 
6674   int type = get_texture_layer_type(op, "type");
6675   proj_paint_default_color(op, type, ma);
6676 
6677   if (proj_paint_add_slot(C, op)) {
6678     return OPERATOR_FINISHED;
6679   }
6680   return OPERATOR_CANCELLED;
6681 }
6682 
get_default_texture_layer_name_for_object(Object * ob,int texture_type,char * dst,int dst_length)6683 static void get_default_texture_layer_name_for_object(Object *ob,
6684                                                       int texture_type,
6685                                                       char *dst,
6686                                                       int dst_length)
6687 {
6688   Material *ma = BKE_object_material_get(ob, ob->actcol);
6689   const char *base_name = ma ? &ma->id.name[2] : &ob->id.name[2];
6690   BLI_snprintf(dst, dst_length, "%s %s", base_name, layer_type_items[texture_type].name);
6691 }
6692 
texture_paint_add_texture_paint_slot_invoke(bContext * C,wmOperator * op,const wmEvent * UNUSED (event))6693 static int texture_paint_add_texture_paint_slot_invoke(bContext *C,
6694                                                        wmOperator *op,
6695                                                        const wmEvent *UNUSED(event))
6696 {
6697   /* Get material and default color to display in the popup. */
6698   Object *ob = ED_object_active_context(C);
6699   Material *ma = get_or_create_current_material(C, ob);
6700 
6701   int type = get_texture_layer_type(op, "type");
6702   proj_paint_default_color(op, type, ma);
6703 
6704   char imagename[MAX_ID_NAME - 2];
6705   get_default_texture_layer_name_for_object(ob, type, (char *)&imagename, sizeof(imagename));
6706   RNA_string_set(op->ptr, "name", imagename);
6707 
6708   return WM_operator_props_dialog_popup(C, op, 300);
6709 }
6710 
6711 #define IMA_DEF_NAME N_("Untitled")
6712 
PAINT_OT_add_texture_paint_slot(wmOperatorType * ot)6713 void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
6714 {
6715   PropertyRNA *prop;
6716   static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
6717 
6718   /* identifiers */
6719   ot->name = "Add Texture Paint Slot";
6720   ot->description = "Add a texture paint slot";
6721   ot->idname = "PAINT_OT_add_texture_paint_slot";
6722 
6723   /* api callbacks */
6724   ot->invoke = texture_paint_add_texture_paint_slot_invoke;
6725   ot->exec = texture_paint_add_texture_paint_slot_exec;
6726   ot->poll = ED_operator_object_active_editable_mesh;
6727 
6728   /* flags */
6729   ot->flag = OPTYPE_UNDO;
6730 
6731   /* properties */
6732   prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
6733   RNA_def_property_flag(prop, PROP_HIDDEN);
6734   RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
6735   prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
6736   RNA_def_property_subtype(prop, PROP_PIXEL);
6737   prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
6738   RNA_def_property_subtype(prop, PROP_PIXEL);
6739   prop = RNA_def_float_color(
6740       ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
6741   RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
6742   RNA_def_property_float_array_default(prop, default_color);
6743   RNA_def_boolean(ot->srna, "alpha", true, "Alpha", "Create an image with an alpha channel");
6744   RNA_def_enum(ot->srna,
6745                "generated_type",
6746                rna_enum_image_generated_type_items,
6747                IMA_GENTYPE_BLANK,
6748                "Generated Type",
6749                "Fill the image with a grid for UV map testing");
6750   RNA_def_boolean(
6751       ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
6752 }
6753 
add_simple_uvs_exec(bContext * C,wmOperator * UNUSED (op))6754 static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
6755 {
6756   /* no checks here, poll function does them for us */
6757   Main *bmain = CTX_data_main(C);
6758   Object *ob = CTX_data_active_object(C);
6759   Scene *scene = CTX_data_scene(C);
6760 
6761   ED_uvedit_add_simple_uvs(bmain, scene, ob);
6762 
6763   ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
6764 
6765   DEG_id_tag_update(ob->data, 0);
6766   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
6767   WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
6768   return OPERATOR_FINISHED;
6769 }
6770 
add_simple_uvs_poll(bContext * C)6771 static bool add_simple_uvs_poll(bContext *C)
6772 {
6773   Object *ob = CTX_data_active_object(C);
6774 
6775   if (!ob || ob->type != OB_MESH || ob->mode != OB_MODE_TEXTURE_PAINT) {
6776     return false;
6777   }
6778   return true;
6779 }
6780 
PAINT_OT_add_simple_uvs(wmOperatorType * ot)6781 void PAINT_OT_add_simple_uvs(wmOperatorType *ot)
6782 {
6783   /* identifiers */
6784   ot->name = "Add simple UVs";
6785   ot->description = "Add cube map uvs on mesh";
6786   ot->idname = "PAINT_OT_add_simple_uvs";
6787 
6788   /* api callbacks */
6789   ot->exec = add_simple_uvs_exec;
6790   ot->poll = add_simple_uvs_poll;
6791 
6792   /* flags */
6793   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
6794 }
6795