Blender  V2.59
paint_image.c
Go to the documentation of this file.
00001 /*
00002  * $Id: paint_image.c 38893 2011-08-01 08:53:57Z campbellbarton $
00003  * imagepaint.c
00004  *
00005  * Functions to paint images in 2D and 3D.
00006  * 
00007  * ***** BEGIN GPL LICENSE BLOCK *****
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * along with this program; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00023  * All rights reserved.
00024  *
00025  * The Original Code is: some of this file.
00026  *
00027  * Contributor(s): Jens Ole Wund (bjornmose), Campbell Barton (ideasman42)
00028  *
00029  * ***** END GPL LICENSE BLOCK *****
00030  */
00031 
00037 #include <float.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 #include <math.h>
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #ifdef WIN32
00045 #include "BLI_winstuff.h"
00046 #endif
00047 #include "BLI_math.h"
00048 #include "BLI_blenlib.h"
00049 #include "BLI_dynstr.h"
00050 #include "BLI_linklist.h"
00051 #include "BLI_memarena.h"
00052 #include "BLI_threads.h"
00053 #include "BLI_utildefines.h"
00054 
00055 #include "PIL_time.h"
00056 
00057 #include "IMB_imbuf.h"
00058 #include "IMB_imbuf_types.h"
00059 
00060 #include "DNA_brush_types.h"
00061 #include "DNA_mesh_types.h"
00062 #include "DNA_meshdata_types.h"
00063 #include "DNA_object_types.h"
00064 #include "DNA_scene_types.h"
00065 #include "DNA_texture_types.h"
00066 
00067 #include "BKE_context.h"
00068 #include "BKE_depsgraph.h"
00069 #include "BKE_DerivedMesh.h"
00070 #include "BKE_idprop.h"
00071 #include "BKE_brush.h"
00072 #include "BKE_image.h"
00073 #include "BKE_library.h"
00074 #include "BKE_main.h"
00075 #include "BKE_mesh.h"
00076 #include "BKE_node.h"
00077 #include "BKE_object.h"
00078 #include "BKE_paint.h"
00079 #include "BKE_report.h"
00080 
00081 #include "BIF_gl.h"
00082 #include "BIF_glutil.h"
00083 
00084 #include "UI_view2d.h"
00085 
00086 #include "ED_image.h"
00087 #include "ED_screen.h"
00088 #include "ED_sculpt.h"
00089 #include "ED_view3d.h"
00090 
00091 #include "WM_api.h"
00092 #include "WM_types.h"
00093 
00094 #include "RNA_access.h"
00095 #include "RNA_define.h"
00096 #include "RNA_enum_types.h"
00097 
00098 #include "GPU_draw.h"
00099 
00100 #include "paint_intern.h"
00101 
00102 /* Defines and Structs */
00103 
00104 #define IMAPAINT_CHAR_TO_FLOAT(c) ((c)/255.0f)
00105 
00106 #define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); }
00107 #define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); (c)[3]=FTOCHAR((f)[3]); }
00108 
00109 #define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); }
00110 #define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); (f)[3]=IMAPAINT_CHAR_TO_FLOAT((c)[3]); }
00111 #define IMAPAINT_FLOAT_RGB_COPY(a, b) VECCOPY(a, b)
00112 
00113 #define IMAPAINT_TILE_BITS                      6
00114 #define IMAPAINT_TILE_SIZE                      (1 << IMAPAINT_TILE_BITS)
00115 #define IMAPAINT_TILE_NUMBER(size)      (((size)+IMAPAINT_TILE_SIZE-1) >> IMAPAINT_TILE_BITS)
00116 
00117 static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
00118 
00119 
00120 typedef struct ImagePaintState {
00121         SpaceImage *sima;
00122         View2D *v2d;
00123         Scene *scene;
00124         bScreen *screen;
00125 
00126         Brush *brush;
00127         short tool, blend;
00128         Image *image;
00129         ImBuf *canvas;
00130         ImBuf *clonecanvas;
00131         short clonefreefloat;
00132         char *warnpackedfile;
00133         char *warnmultifile;
00134 
00135         /* texture paint only */
00136         Object *ob;
00137         Mesh *me;
00138         int faceindex;
00139         float uv[2];
00140 } ImagePaintState;
00141 
00142 typedef struct ImagePaintPartialRedraw {
00143         int x1, y1, x2, y2;
00144         int enabled;
00145 } ImagePaintPartialRedraw;
00146 
00147 typedef struct ImagePaintRegion {
00148         int destx, desty;
00149         int srcx, srcy;
00150         int width, height;
00151 } ImagePaintRegion;
00152 
00153 /* ProjectionPaint defines */
00154 
00155 /* approx the number of buckets to have under the brush,
00156  * used with the brush size to set the ps->buckets_x and ps->buckets_y value.
00157  * 
00158  * When 3 - a brush should have ~9 buckets under it at once
00159  * ...this helps for threading while painting as well as
00160  * avoiding initializing pixels that wont touch the brush */
00161 #define PROJ_BUCKET_BRUSH_DIV 4
00162 
00163 #define PROJ_BUCKET_RECT_MIN 4
00164 #define PROJ_BUCKET_RECT_MAX 256
00165 
00166 #define PROJ_BOUNDBOX_DIV 8
00167 #define PROJ_BOUNDBOX_SQUARED  (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV)
00168 
00169 //#define PROJ_DEBUG_PAINT 1
00170 //#define PROJ_DEBUG_NOSEAMBLEED 1
00171 //#define PROJ_DEBUG_PRINT_CLIP 1
00172 #define PROJ_DEBUG_WINCLIP 1
00173 
00174 /* projectFaceSeamFlags options */
00175 //#define PROJ_FACE_IGNORE      (1<<0)  /* When the face is hidden, backfacing or occluded */
00176 //#define PROJ_FACE_INIT        (1<<1)  /* When we have initialized the faces data */
00177 #define PROJ_FACE_SEAM1 (1<<0)  /* If this face has a seam on any of its edges */
00178 #define PROJ_FACE_SEAM2 (1<<1)
00179 #define PROJ_FACE_SEAM3 (1<<2)
00180 #define PROJ_FACE_SEAM4 (1<<3)
00181 
00182 #define PROJ_FACE_NOSEAM1       (1<<4)
00183 #define PROJ_FACE_NOSEAM2       (1<<5)
00184 #define PROJ_FACE_NOSEAM3       (1<<6)
00185 #define PROJ_FACE_NOSEAM4       (1<<7)
00186 
00187 #define PROJ_SRC_VIEW           1
00188 #define PROJ_SRC_IMAGE_CAM      2
00189 #define PROJ_SRC_IMAGE_VIEW     3
00190 
00191 #define PROJ_VIEW_DATA_ID "view_data"
00192 #define PROJ_VIEW_DATA_SIZE (4*4 + 4*4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */
00193 
00194 
00195 /* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams
00196  * as this number approaches  1.0f the likelihood increases of float precision errors where
00197  * it is occluded by an adjacent face */
00198 #define PROJ_FACE_SCALE_SEAM    0.99f
00199 
00200 #define PROJ_BUCKET_NULL                0
00201 #define PROJ_BUCKET_INIT                (1<<0)
00202 // #define PROJ_BUCKET_CLONE_INIT       (1<<1)
00203 
00204 /* used for testing doubles, if a point is on a line etc */
00205 #define PROJ_GEOM_TOLERANCE 0.00075f
00206 
00207 /* vert flags */
00208 #define PROJ_VERT_CULL 1
00209 
00210 #define PI_80_DEG ((M_PI_2 / 9) * 8)
00211 
00212 /* This is mainly a convenience struct used so we can keep an array of images we use
00213  * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
00214  * because 'partRedrawRect' and 'touch' values would not be thread safe */
00215 typedef struct ProjPaintImage {
00216         Image *ima;
00217         ImBuf *ibuf;
00218         ImagePaintPartialRedraw *partRedrawRect;
00219         void **undoRect; /* only used to build undo tiles after painting */
00220         int touch;
00221 } ProjPaintImage;
00222 
00223 /* Main projection painting struct passed to all projection painting functions */
00224 typedef struct ProjPaintState {
00225         View3D *v3d;
00226         RegionView3D *rv3d;
00227         ARegion *ar;
00228         Scene *scene;
00229         int source; /* PROJ_SRC_**** */
00230 
00231         Brush *brush;
00232         short tool, blend;
00233         Object *ob;
00234         /* end similarities with ImagePaintState */
00235         
00236         DerivedMesh    *dm;
00237         int                     dm_totface;
00238         int                     dm_totvert;
00239         int                             dm_release;
00240         
00241         MVert              *dm_mvert;
00242         MFace              *dm_mface;
00243         MTFace             *dm_mtface;
00244         MTFace             *dm_mtface_clone;    /* other UV layer, use for cloning between layers */
00245         MTFace             *dm_mtface_stencil;
00246         
00247         /* projection painting only */
00248         MemArena *arena_mt[BLENDER_MAX_THREADS];/* for multithreading, the first item is sometimes used for non threaded cases too */
00249         LinkNode **bucketRect;                          /* screen sized 2D array, each pixel has a linked list of ProjPixel's */
00250         LinkNode **bucketFaces;                         /* bucketRect aligned array linkList of faces overlapping each bucket */
00251         unsigned char *bucketFlags;                                     /* store if the bucks have been initialized  */
00252 #ifndef PROJ_DEBUG_NOSEAMBLEED
00253         char *faceSeamFlags;                            /* store info about faces, if they are initialized etc*/
00254         float (*faceSeamUVs)[4][2];                     /* expanded UVs for faces to use as seams */
00255         LinkNode **vertFaces;                           /* Only needed for when seam_bleed_px is enabled, use to find UV seams */
00256 #endif
00257         char *vertFlags;                                        /* store options per vert, now only store if the vert is pointing away from the view */
00258         int buckets_x;                                          /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */
00259         int buckets_y;
00260         
00261         ProjPaintImage *projImages;
00262         
00263         int image_tot;                          /* size of projectImages array */
00264         
00265         float (*screenCoords)[4];       /* verts projected into floating point screen space */
00266         
00267         float screenMin[2];                     /* 2D bounds for mesh verts on the screen's plane (screenspace) */
00268         float screenMax[2]; 
00269         float screen_width;                     /* Calculated from screenMin & screenMax */
00270         float screen_height;
00271         int winx, winy;                         /* from the carea or from the projection render */
00272         
00273         /* options for projection painting */
00274         int do_layer_clone;
00275         int do_layer_stencil;
00276         int do_layer_stencil_inv;
00277         
00278         short do_occlude;                       /* Use raytraced occlusion? - ortherwise will paint right through to the back*/
00279         short do_backfacecull;  /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */
00280         short do_mask_normal;                   /* mask out pixels based on their normals */
00281         float normal_angle;                             /* what angle to mask at*/
00282         float normal_angle_inner;
00283         float normal_angle_range;               /* difference between normal_angle and normal_angle_inner, for easy access */
00284         
00285         short is_ortho;
00286         short is_airbrush;                                      /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */
00287         short is_texbrush;                                      /* only to avoid running  */
00288 #ifndef PROJ_DEBUG_NOSEAMBLEED
00289         float seam_bleed_px;
00290 #endif
00291         /* clone vars */
00292         float cloneOffset[2];
00293         
00294         float projectMat[4][4];         /* Projection matrix, use for getting screen coords */
00295         float viewDir[3];                       /* View vector, use for do_backfacecull and for ray casting with an ortho viewport  */
00296         float viewPos[3];                       /* View location in object relative 3D space, so can compare to verts  */
00297         float clipsta, clipend;
00298         
00299         /* reproject vars */
00300         Image *reproject_image;
00301         ImBuf *reproject_ibuf;
00302 
00303 
00304         /* threads */
00305         int thread_tot;
00306         int bucketMin[2];
00307         int bucketMax[2];
00308         int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */
00309 } ProjPaintState;
00310 
00311 typedef union pixelPointer
00312 {
00313         float *f_pt;                    /* float buffer */
00314         unsigned int *uint_pt; /* 2 ways to access a char buffer */
00315         unsigned char *ch_pt;
00316 } PixelPointer;
00317 
00318 typedef union pixelStore
00319 {
00320         unsigned char ch[4];
00321         unsigned int uint;
00322         float f[4];
00323 } PixelStore;
00324 
00325 typedef struct ProjPixel {
00326         float projCoSS[2]; /* the floating point screen projection of this pixel */
00327         
00328         /* Only used when the airbrush is disabled.
00329          * Store the max mask value to avoid painting over an area with a lower opacity
00330          * with an advantage that we can avoid touching the pixel at all, if the 
00331          * new mask value is lower then mask_max */
00332         unsigned short mask_max;
00333         
00334         /* for various reasons we may want to mask out painting onto this pixel */
00335         unsigned short mask;
00336         
00337         short x_px, y_px;
00338         
00339         PixelStore origColor;
00340         PixelStore newColor;
00341         PixelPointer pixel;
00342         
00343         short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */
00344         unsigned char bb_cell_index;
00345 } ProjPixel;
00346 
00347 typedef struct ProjPixelClone {
00348         struct ProjPixel __pp;
00349         PixelStore clonepx;
00350 } ProjPixelClone;
00351 
00352 /* Finish projection painting structs */
00353 
00354 typedef struct UndoImageTile {
00355         struct UndoImageTile *next, *prev;
00356 
00357         char idname[MAX_ID_NAME];       /* name instead of pointer*/
00358 
00359         void *rect;
00360         int x, y;
00361 } UndoImageTile;
00362 
00363 static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
00364 
00365 /* UNDO */
00366 
00367 static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore)
00368 {
00369         /* copy or swap contents of tile->rect and region in ibuf->rect */
00370         IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE,
00371                 tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
00372 
00373         if(ibuf->rect_float) {
00374                 SWAP(void*, tmpibuf->rect_float, tile->rect);
00375         } else {
00376                 SWAP(void*, tmpibuf->rect, tile->rect);
00377         }
00378         
00379         if(restore)
00380                 IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE,
00381                         tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
00382 }
00383 
00384 static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile)
00385 {
00386         ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_IMAGE);
00387         UndoImageTile *tile;
00388         int allocsize;
00389 
00390         for(tile=lb->first; tile; tile=tile->next)
00391                 if(tile->x == x_tile && tile->y == y_tile && strcmp(tile->idname, ima->id.name)==0)
00392                         return tile->rect;
00393         
00394         if (*tmpibuf==NULL)
00395                 *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat|IB_rect);
00396         
00397         tile= MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
00398         strcpy(tile->idname, ima->id.name);
00399         tile->x= x_tile;
00400         tile->y= y_tile;
00401 
00402         allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4;
00403         allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char);
00404         tile->rect= MEM_mapallocN(allocsize, "UndeImageTile.rect");
00405 
00406         undo_copy_tile(tile, *tmpibuf, ibuf, 0);
00407         undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
00408 
00409         BLI_addtail(lb, tile);
00410         
00411         return tile->rect;
00412 }
00413 
00414 static void image_undo_restore(bContext *C, ListBase *lb)
00415 {
00416         Main *bmain= CTX_data_main(C);
00417         Image *ima = NULL;
00418         ImBuf *ibuf, *tmpibuf;
00419         UndoImageTile *tile;
00420 
00421         tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
00422                                                         IB_rectfloat|IB_rect);
00423         
00424         for(tile=lb->first; tile; tile=tile->next) {
00425                 /* find image based on name, pointer becomes invalid with global undo */
00426                 if(ima && strcmp(tile->idname, ima->id.name)==0);
00427                 else {
00428                         for(ima=bmain->image.first; ima; ima=ima->id.next)
00429                                 if(strcmp(tile->idname, ima->id.name)==0)
00430                                         break;
00431                 }
00432 
00433                 ibuf= BKE_image_get_ibuf(ima, NULL);
00434 
00435                 if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
00436                         continue;
00437 
00438                 undo_copy_tile(tile, tmpibuf, ibuf, 1);
00439 
00440                 GPU_free_image(ima); /* force OpenGL reload */
00441                 if(ibuf->rect_float)
00442                         ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
00443                 if(ibuf->mipmap[0])
00444                         ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
00445 
00446         }
00447 
00448         IMB_freeImBuf(tmpibuf);
00449 }
00450 
00451 static void image_undo_free(ListBase *lb)
00452 {
00453         UndoImageTile *tile;
00454 
00455         for(tile=lb->first; tile; tile=tile->next)
00456                 MEM_freeN(tile->rect);
00457 }
00458 
00459 /* fast projection bucket array lookup, use the safe version for bound checking  */
00460 static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2])
00461 {
00462         /* If we were not dealing with screenspace 2D coords we could simple do...
00463          * ps->bucketRect[x + (y*ps->buckets_y)] */
00464         
00465         /* please explain?
00466          * projCoSS[0] - ps->screenMin[0]       : zero origin
00467          * ... / ps->screen_width                               : range from 0.0 to 1.0
00468          * ... * ps->buckets_x          : use as a bucket index
00469          *
00470          * Second multiplication does similar but for vertical offset
00471          */
00472         return  (       (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width)  * ps->buckets_x)) + 
00473                 (       (       (int)(((projCoSS[1] - ps->screenMin[1])  / ps->screen_height) * ps->buckets_y)) * ps->buckets_x);
00474 }
00475 
00476 static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2])
00477 {
00478         int bucket_index = project_bucket_offset(ps, projCoSS);
00479         
00480         if (bucket_index < 0 || bucket_index >= ps->buckets_x*ps->buckets_y) {  
00481                 return -1;
00482         }
00483         else {
00484                 return bucket_index;
00485         }
00486 }
00487 
00488 /* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */
00489 static void barycentric_weights_v2_persp(float v1[4], float v2[4], float v3[4], float co[2], float w[3])
00490 {
00491         float wtot_inv, wtot;
00492 
00493         w[0] = area_tri_signed_v2(v2, v3, co) / v1[3];
00494         w[1] = area_tri_signed_v2(v3, v1, co) / v2[3];
00495         w[2] = area_tri_signed_v2(v1, v2, co) / v3[3];
00496         wtot = w[0]+w[1]+w[2];
00497 
00498         if (wtot != 0.0f) {
00499                 wtot_inv = 1.0f/wtot;
00500 
00501                 w[0] = w[0]*wtot_inv;
00502                 w[1] = w[1]*wtot_inv;
00503                 w[2] = w[2]*wtot_inv;
00504         }
00505         else /* dummy values for zero area face */
00506                 w[0] = w[1] = w[2] = 1.0f/3.0f;
00507 }
00508 
00509 static float VecZDepthOrtho(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
00510 {
00511         barycentric_weights_v2(v1, v2, v3, pt, w);
00512         return (v1[2]*w[0]) + (v2[2]*w[1]) + (v3[2]*w[2]);
00513 }
00514 
00515 static float VecZDepthPersp(float pt[2], float v1[3], float v2[3], float v3[3], float w[3])
00516 {
00517         float wtot_inv, wtot;
00518         float w_tmp[3];
00519 
00520         barycentric_weights_v2_persp(v1, v2, v3, pt, w);
00521         /* for the depth we need the weights to match what
00522          * barycentric_weights_v2 would return, in this case its easiest just to
00523          * undo the 4th axis division and make it unit-sum
00524          *
00525          * don't call barycentric_weights_v2() becaue our callers expect 'w'
00526          * to be weighted from the perspective */
00527         w_tmp[0]= w[0] * v1[3];
00528         w_tmp[1]= w[1] * v2[3];
00529         w_tmp[2]= w[2] * v3[3];
00530 
00531         wtot = w_tmp[0]+w_tmp[1]+w_tmp[2];
00532 
00533         if (wtot != 0.0f) {
00534                 wtot_inv = 1.0f/wtot;
00535 
00536                 w_tmp[0] = w_tmp[0]*wtot_inv;
00537                 w_tmp[1] = w_tmp[1]*wtot_inv;
00538                 w_tmp[2] = w_tmp[2]*wtot_inv;
00539         }
00540         else /* dummy values for zero area face */
00541                 w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f/3.0f;
00542         /* done mimicing barycentric_weights_v2() */
00543 
00544         return (v1[2]*w_tmp[0]) + (v2[2]*w_tmp[1]) + (v3[2]*w_tmp[2]);
00545 }
00546 
00547 
00548 /* Return the top-most face index that the screen space coord 'pt' touches (or -1) */
00549 static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w[3], int *side)
00550 {
00551         LinkNode *node;
00552         float w_tmp[3];
00553         float *v1, *v2, *v3, *v4;
00554         int bucket_index;
00555         int face_index;
00556         int best_side = -1;
00557         int best_face_index = -1;
00558         float z_depth_best = FLT_MAX, z_depth;
00559         MFace *mf;
00560         
00561         bucket_index = project_bucket_offset_safe(ps, pt);
00562         if (bucket_index==-1)
00563                 return -1;
00564         
00565         
00566         
00567         /* we could return 0 for 1 face buckets, as long as this function assumes
00568          * that the point its testing is only every originated from an existing face */
00569         
00570         for (node= ps->bucketFaces[bucket_index]; node; node= node->next) {
00571                 face_index = GET_INT_FROM_POINTER(node->link);
00572                 mf= ps->dm_mface + face_index;
00573                 
00574                 v1= ps->screenCoords[mf->v1];
00575                 v2= ps->screenCoords[mf->v2];
00576                 v3= ps->screenCoords[mf->v3];
00577                 
00578                 if (isect_point_tri_v2(pt, v1, v2, v3)) {
00579                         if (ps->is_ortho)       z_depth= VecZDepthOrtho(pt, v1, v2, v3, w_tmp);
00580                         else                            z_depth= VecZDepthPersp(pt, v1, v2, v3, w_tmp);
00581                         
00582                         if (z_depth < z_depth_best) {
00583                                 best_face_index = face_index;
00584                                 best_side = 0;
00585                                 z_depth_best = z_depth;
00586                                 VECCOPY(w, w_tmp);
00587                         }
00588                 }
00589                 else if (mf->v4) {
00590                         v4= ps->screenCoords[mf->v4];
00591                         
00592                         if (isect_point_tri_v2(pt, v1, v3, v4)) {
00593                                 if (ps->is_ortho)       z_depth= VecZDepthOrtho(pt, v1, v3, v4, w_tmp);
00594                                 else                            z_depth= VecZDepthPersp(pt, v1, v3, v4, w_tmp);
00595 
00596                                 if (z_depth < z_depth_best) {
00597                                         best_face_index = face_index;
00598                                         best_side= 1;
00599                                         z_depth_best = z_depth;
00600                                         VECCOPY(w, w_tmp);
00601                                 }
00602                         }
00603                 }
00604         }
00605         
00606         *side = best_side;
00607         return best_face_index; /* will be -1 or a valid face */
00608 }
00609 
00610 /* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */
00611 static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y)
00612 {
00613         /* use */
00614         *x = (float)fmodf(uv[0], 1.0f);
00615         *y = (float)fmodf(uv[1], 1.0f);
00616         
00617         if (*x < 0.0f) *x += 1.0f;
00618         if (*y < 0.0f) *y += 1.0f;
00619         
00620         *x = *x * ibuf_x - 0.5f;
00621         *y = *y * ibuf_y - 0.5f;
00622 }
00623 
00624 /* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */
00625 static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float *rgba_fp, unsigned char *rgba, const int interp)
00626 {
00627         float w[3], uv[2];
00628         int side;
00629         int face_index;
00630         MTFace *tf;
00631         ImBuf *ibuf;
00632         int xi, yi;
00633         
00634         
00635         face_index = project_paint_PickFace(ps, pt, w, &side);
00636         
00637         if (face_index == -1)
00638                 return 0;
00639         
00640         tf = ps->dm_mtface + face_index;
00641         
00642         if (side == 0) {
00643                 interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[1], tf->uv[2], w);
00644         }
00645         else { /* QUAD */
00646                 interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w);
00647         }
00648         
00649         ibuf = tf->tpage->ibufs.first; /* we must have got the imbuf before getting here */
00650         if (!ibuf) return 0;
00651         
00652         if (interp) {
00653                 float x, y;
00654                 uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y);
00655                 
00656                 if (ibuf->rect_float) {
00657                         if (rgba_fp) {
00658                                 bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y);
00659                         }
00660                         else {
00661                                 float rgba_tmp_f[4];
00662                                 bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y);
00663                                 IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f);
00664                         }
00665                 }
00666                 else {
00667                         if (rgba) {
00668                                 bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y);
00669                         }
00670                         else {
00671                                 unsigned char rgba_tmp[4];
00672                                 bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y);
00673                                 IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp);
00674                         }
00675                 }
00676         }
00677         else {
00678                 //xi = (int)((uv[0]*ibuf->x) + 0.5f);
00679                 //yi = (int)((uv[1]*ibuf->y) + 0.5f);
00680                 //if (xi<0 || xi>=ibuf->x  ||  yi<0 || yi>=ibuf->y) return 0;
00681                 
00682                 /* wrap */
00683                 xi = ((int)(uv[0]*ibuf->x)) % ibuf->x;
00684                 if (xi<0) xi += ibuf->x;
00685                 yi = ((int)(uv[1]*ibuf->y)) % ibuf->y;
00686                 if (yi<0) yi += ibuf->y;
00687                 
00688                 
00689                 if (rgba) {
00690                         if (ibuf->rect_float) {
00691                                 float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4);
00692                                 IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp);
00693                         }
00694                         else {
00695                                 *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4));
00696                         }
00697                 }
00698                 
00699                 if (rgba_fp) {
00700                         if (ibuf->rect_float) {
00701                                 QUATCOPY(rgba_fp, ((float *)ibuf->rect_float + ((xi + yi * ibuf->x) * 4)));
00702                         }
00703                         else {
00704                                 char *tmp_ch= ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4);
00705                                 IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch);
00706                         }
00707                 }
00708         }
00709         return 1;
00710 }
00711 
00712 /* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
00713  * return...
00714  *  0   : no occlusion
00715  * -1   : no occlusion but 2D intersection is true (avoid testing the other half of a quad)
00716  *  1   : occluded
00717         2       : occluded with w[3] weights set (need to know in some cases) */
00718 
00719 static int project_paint_occlude_ptv(float pt[3], float v1[3], float v2[3], float v3[3], float w[3], int is_ortho)
00720 {
00721         /* if all are behind us, return false */
00722         if(v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2])
00723                 return 0;
00724                 
00725         /* do a 2D point in try intersection */
00726         if (!isect_point_tri_v2(pt, v1, v2, v3))
00727                 return 0; /* we know there is  */
00728         
00729 
00730         /* From here on we know there IS an intersection */
00731         /* if ALL of the verts are infront of us then we know it intersects ? */
00732         if(v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) {
00733                 return 1;
00734         }
00735         else {
00736                 /* we intersect? - find the exact depth at the point of intersection */
00737                 /* Is this point is occluded by another face? */
00738                 if (is_ortho) {
00739                         if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2;
00740                 }
00741                 else {
00742                         if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2;
00743                 }
00744         }
00745         return -1;
00746 }
00747 
00748 
00749 static int project_paint_occlude_ptv_clip(
00750                 const ProjPaintState *ps, const MFace *mf,
00751                 float pt[3], float v1[3], float v2[3], float v3[3],
00752                 const int side )
00753 {
00754         float w[3], wco[3];
00755         int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho);
00756 
00757         if (ret <= 0)
00758                 return ret;
00759 
00760         if (ret==1) { /* weights not calculated */
00761                 if (ps->is_ortho)       barycentric_weights_v2(v1, v2, v3, pt, w);
00762                 else                            barycentric_weights_v2_persp(v1, v2, v3, pt, w);
00763         }
00764 
00765         /* Test if we're in the clipped area, */
00766         if (side)       interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
00767         else            interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
00768         
00769         if(!ED_view3d_test_clipping(ps->rv3d, wco, 1)) {
00770                 return 1;
00771         }
00772         
00773         return -1;
00774 }
00775 
00776 
00777 /* Check if a screenspace location is occluded by any other faces
00778  * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison
00779  * and dosn't need to be correct in relation to X and Y coords (this is the case in perspective view) */
00780 static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, float pixelScreenCo[4])
00781 {
00782         MFace *mf;
00783         int face_index;
00784         int isect_ret;
00785         float w[3]; /* not needed when clipping */
00786         const short do_clip= ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
00787         
00788         /* we could return 0 for 1 face buckets, as long as this function assumes
00789          * that the point its testing is only every originated from an existing face */
00790 
00791         for (; bucketFace; bucketFace = bucketFace->next) {
00792                 face_index = GET_INT_FROM_POINTER(bucketFace->link);
00793 
00794                 if (orig_face != face_index) {
00795                         mf = ps->dm_mface + face_index;
00796                         if(do_clip)
00797                                 isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0);
00798                         else
00799                                 isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho);
00800 
00801                         /* Note, if isect_ret==-1 then we dont want to test the other side of the quad */
00802                         if (isect_ret==0 && mf->v4) {
00803                                 if(do_clip)
00804                                         isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1);
00805                                 else
00806                                         isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho);
00807                         }
00808                         if (isect_ret>=1) {
00809                                 /* TODO - we may want to cache the first hit,
00810                                  * it is not possible to swap the face order in the list anymore */
00811                                 return 1;
00812                         }
00813                 }
00814         }
00815         return 0;
00816 }
00817 
00818 /* basic line intersection, could move to math_geom.c, 2 points with a horiz line
00819  * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */
00820 #define ISECT_TRUE 1
00821 #define ISECT_TRUE_P1 2
00822 #define ISECT_TRUE_P2 3
00823 static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect)
00824 {
00825         float y_diff;
00826         
00827         if (y_level==p1[1]) { /* are we touching the first point? - no interpolation needed */
00828                 *x_isect = p1[0];
00829                 return ISECT_TRUE_P1;
00830         }
00831         if (y_level==p2[1]) { /* are we touching the second point? - no interpolation needed */
00832                 *x_isect = p2[0];
00833                 return ISECT_TRUE_P2;
00834         }
00835         
00836         y_diff= fabsf(p1[1]-p2[1]); /* yuck, horizontal line, we cant do much here */
00837         
00838         if (y_diff < 0.000001f) {
00839                 *x_isect = (p1[0]+p2[0]) * 0.5f;
00840                 return ISECT_TRUE;              
00841         }
00842         
00843         if (p1[1] > y_level && p2[1] < y_level) {
00844                 *x_isect = (p2[0]*(p1[1]-y_level) + p1[0]*(y_level-p2[1])) / y_diff;  /*(p1[1]-p2[1]);*/
00845                 return ISECT_TRUE;
00846         }
00847         else if (p1[1] < y_level && p2[1] > y_level) {
00848                 *x_isect = (p2[0]*(y_level-p1[1]) + p1[0]*(p2[1]-y_level)) / y_diff;  /*(p2[1]-p1[1]);*/
00849                 return ISECT_TRUE;
00850         }
00851         else {
00852                 return 0;
00853         }
00854 }
00855 
00856 static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect)
00857 {
00858         float x_diff;
00859         
00860         if (x_level==p1[0]) { /* are we touching the first point? - no interpolation needed */
00861                 *y_isect = p1[1];
00862                 return ISECT_TRUE_P1;
00863         }
00864         if (x_level==p2[0]) { /* are we touching the second point? - no interpolation needed */
00865                 *y_isect = p2[1];
00866                 return ISECT_TRUE_P2;
00867         }
00868         
00869         x_diff= fabsf(p1[0]-p2[0]); /* yuck, horizontal line, we cant do much here */
00870         
00871         if (x_diff < 0.000001f) { /* yuck, vertical line, we cant do much here */
00872                 *y_isect = (p1[0]+p2[0]) * 0.5f;
00873                 return ISECT_TRUE;              
00874         }
00875         
00876         if (p1[0] > x_level && p2[0] < x_level) {
00877                 *y_isect = (p2[1]*(p1[0]-x_level) + p1[1]*(x_level-p2[0])) / x_diff; /*(p1[0]-p2[0]);*/
00878                 return ISECT_TRUE;
00879         }
00880         else if (p1[0] < x_level && p2[0] > x_level) {
00881                 *y_isect = (p2[1]*(x_level-p1[0]) + p1[1]*(p2[0]-x_level)) / x_diff; /*(p2[0]-p1[0]);*/
00882                 return ISECT_TRUE;
00883         }
00884         else {
00885                 return 0;
00886         }
00887 }
00888 
00889 /* simple func use for comparing UV locations to check if there are seams.
00890  * Its possible this gives incorrect results, when the UVs for 1 face go into the next 
00891  * tile, but do not do this for the adjacent face, it could return a false positive.
00892  * This is so unlikely that Id not worry about it. */
00893 #ifndef PROJ_DEBUG_NOSEAMBLEED
00894 static int cmp_uv(const float vec2a[2], const float vec2b[2])
00895 {
00896         /* if the UV's are not between 0.0 and 1.0 */
00897         float xa = (float)fmodf(vec2a[0], 1.0f);
00898         float ya = (float)fmodf(vec2a[1], 1.0f);
00899         
00900         float xb = (float)fmodf(vec2b[0], 1.0f);
00901         float yb = (float)fmodf(vec2b[1], 1.0f);        
00902         
00903         if (xa < 0.0f) xa += 1.0f;
00904         if (ya < 0.0f) ya += 1.0f;
00905         
00906         if (xb < 0.0f) xb += 1.0f;
00907         if (yb < 0.0f) yb += 1.0f;
00908         
00909         return ((fabsf(xa-xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya-yb) < PROJ_GEOM_TOLERANCE)) ? 1:0;
00910 }
00911 #endif
00912 
00913 /* set min_px and max_px to the image space bounds of the UV coords 
00914  * return zero if there is no area in the returned rectangle */
00915 #ifndef PROJ_DEBUG_NOSEAMBLEED
00916 static int pixel_bounds_uv(
00917                 const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2],
00918                 rcti *bounds_px,
00919                 const int ibuf_x, const int ibuf_y,
00920                 int is_quad
00921 ) {
00922         float min_uv[2], max_uv[2]; /* UV bounds */
00923         
00924         INIT_MINMAX2(min_uv, max_uv);
00925         
00926         DO_MINMAX2(uv1, min_uv, max_uv);
00927         DO_MINMAX2(uv2, min_uv, max_uv);
00928         DO_MINMAX2(uv3, min_uv, max_uv);
00929         if (is_quad)
00930                 DO_MINMAX2(uv4, min_uv, max_uv);
00931         
00932         bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
00933         bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
00934         
00935         bounds_px->xmax = (int)(ibuf_x * max_uv[0]) +1;
00936         bounds_px->ymax = (int)(ibuf_y * max_uv[1]) +1;
00937         
00938         /*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
00939         
00940         /* face uses no UV area when quantized to pixels? */
00941         return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
00942 }
00943 #endif
00944 
00945 static int pixel_bounds_array(float (* uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot)
00946 {
00947         float min_uv[2], max_uv[2]; /* UV bounds */
00948         
00949         if (tot==0) {
00950                 return 0;
00951         }
00952         
00953         INIT_MINMAX2(min_uv, max_uv);
00954         
00955         while (tot--) {
00956                 DO_MINMAX2((*uv), min_uv, max_uv);
00957                 uv++;
00958         }
00959         
00960         bounds_px->xmin = (int)(ibuf_x * min_uv[0]);
00961         bounds_px->ymin = (int)(ibuf_y * min_uv[1]);
00962         
00963         bounds_px->xmax = (int)(ibuf_x * max_uv[0]) +1;
00964         bounds_px->ymax = (int)(ibuf_y * max_uv[1]) +1;
00965         
00966         /*printf("%d %d %d %d \n", min_px[0], min_px[1], max_px[0], max_px[1]);*/
00967         
00968         /* face uses no UV area when quantized to pixels? */
00969         return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1;
00970 }
00971 
00972 #ifndef PROJ_DEBUG_NOSEAMBLEED
00973 
00974 /* This function returns 1 if this face has a seam along the 2 face-vert indices
00975  * 'orig_i1_fidx' and 'orig_i2_fidx' */
00976 static int 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)
00977 {
00978         LinkNode *node;
00979         int face_index;
00980         unsigned int i1, i2;
00981         int i1_fidx = -1, i2_fidx = -1; /* index in face */
00982         MFace *mf;
00983         MTFace *tf;
00984         const MFace *orig_mf = ps->dm_mface + orig_face;  
00985         const MTFace *orig_tf = ps->dm_mtface + orig_face;
00986         
00987         /* vert indices from face vert order indices */
00988         i1 = (*(&orig_mf->v1 + orig_i1_fidx));
00989         i2 = (*(&orig_mf->v1 + orig_i2_fidx));
00990         
00991         for (node = ps->vertFaces[i1]; node; node = node->next) {
00992                 face_index = GET_INT_FROM_POINTER(node->link);
00993 
00994                 if (face_index != orig_face) {
00995                         mf = ps->dm_mface + face_index;
00996                         /* could check if the 2 faces images match here,
00997                          * but then there wouldn't be a way to return the opposite face's info */
00998                         
00999                         
01000                         /* We need to know the order of the verts in the adjacent face 
01001                          * set the i1_fidx and i2_fidx to (0,1,2,3) */
01002                         if              (mf->v1==i1)                    i1_fidx = 0;
01003                         else if (mf->v2==i1)                    i1_fidx = 1;
01004                         else if (mf->v3==i1)                    i1_fidx = 2;
01005                         else if (mf->v4 && mf->v4==i1)  i1_fidx = 3;
01006                         
01007                         if              (mf->v1==i2)                    i2_fidx = 0;
01008                         else if (mf->v2==i2)                    i2_fidx = 1;
01009                         else if (mf->v3==i2)                    i2_fidx = 2;
01010                         else if (mf->v4 && mf->v4==i2)  i2_fidx = 3;
01011                         
01012                         /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
01013                         if (i2_fidx != -1) {
01014                                 /* This IS an adjacent face!, now lets check if the UVs are ok */
01015                                 tf = ps->dm_mtface + face_index;
01016                                 
01017                                 /* set up the other face */
01018                                 *other_face = face_index;
01019                                 *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx;
01020                                 
01021                                 /* first test if they have the same image */
01022                                 if (    (orig_tf->tpage == tf->tpage) &&
01023                                                 cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) &&
01024                                                 cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) )
01025                                 {
01026                                         // printf("SEAM (NONE)\n");
01027                                         return 0;
01028                                         
01029                                 }
01030                                 else {
01031                                         // printf("SEAM (UV GAP)\n");
01032                                         return 1;
01033                                 }
01034                         }
01035                 }
01036         }
01037         // printf("SEAM (NO FACE)\n");
01038         *other_face = -1;
01039         return 1;
01040 }
01041 
01042 /* Calculate outset UV's, this is not the same as simply scaling the UVs,
01043  * since the outset coords are a margin that keep an even distance from the original UV's,
01044  * note that the image aspect is taken into account */
01045 static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler, const int ibuf_x, const int ibuf_y, const int is_quad)
01046 {
01047         float a1, a2, a3, a4=0.0f;
01048         float puv[4][2]; /* pixelspace uv's */
01049         float no1[2], no2[2], no3[2], no4[2]; /* normals */
01050         float dir1[2], dir2[2], dir3[2], dir4[2];
01051         float ibuf_inv[2];
01052 
01053         ibuf_inv[0]= 1.0f / (float)ibuf_x;
01054         ibuf_inv[1]= 1.0f / (float)ibuf_y;
01055 
01056         /* make UV's in pixel space so we can */
01057         puv[0][0] = orig_uv[0][0] * ibuf_x;
01058         puv[0][1] = orig_uv[0][1] * ibuf_y;
01059         
01060         puv[1][0] = orig_uv[1][0] * ibuf_x;
01061         puv[1][1] = orig_uv[1][1] * ibuf_y;
01062         
01063         puv[2][0] = orig_uv[2][0] * ibuf_x;
01064         puv[2][1] = orig_uv[2][1] * ibuf_y;
01065         
01066         if (is_quad) {
01067                 puv[3][0] = orig_uv[3][0] * ibuf_x;
01068                 puv[3][1] = orig_uv[3][1] * ibuf_y;
01069         }
01070         
01071         /* face edge directions */
01072         sub_v2_v2v2(dir1, puv[1], puv[0]);
01073         sub_v2_v2v2(dir2, puv[2], puv[1]);
01074         normalize_v2(dir1);
01075         normalize_v2(dir2);
01076         
01077         if (is_quad) {
01078                 sub_v2_v2v2(dir3, puv[3], puv[2]);
01079                 sub_v2_v2v2(dir4, puv[0], puv[3]);
01080                 normalize_v2(dir3);
01081                 normalize_v2(dir4);
01082         }
01083         else {
01084                 sub_v2_v2v2(dir3, puv[0], puv[2]);
01085                 normalize_v2(dir3);
01086         }
01087 
01088         /* TODO - angle_normalized_v2v2(...) * (M_PI/180.0f)
01089          * This is incorrect. Its already given radians but without it wont work.
01090          * need to look into a fix - campbell */
01091         if (is_quad) {
01092                 a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * ((float)M_PI/180.0f));
01093                 a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI/180.0f));
01094                 a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI/180.0f));
01095                 a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * ((float)M_PI/180.0f));
01096         }
01097         else {
01098                 a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * ((float)M_PI/180.0f));
01099                 a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI/180.0f));
01100                 a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI/180.0f));
01101         }
01102         
01103         if (is_quad) {
01104                 sub_v2_v2v2(no1, dir4, dir1);
01105                 sub_v2_v2v2(no2, dir1, dir2);
01106                 sub_v2_v2v2(no3, dir2, dir3);
01107                 sub_v2_v2v2(no4, dir3, dir4);
01108                 normalize_v2(no1);
01109                 normalize_v2(no2);
01110                 normalize_v2(no3);
01111                 normalize_v2(no4);
01112                 mul_v2_fl(no1, a1*scaler);
01113                 mul_v2_fl(no2, a2*scaler);
01114                 mul_v2_fl(no3, a3*scaler);
01115                 mul_v2_fl(no4, a4*scaler);
01116                 add_v2_v2v2(outset_uv[0], puv[0], no1);
01117                 add_v2_v2v2(outset_uv[1], puv[1], no2);
01118                 add_v2_v2v2(outset_uv[2], puv[2], no3);
01119                 add_v2_v2v2(outset_uv[3], puv[3], no4);
01120                 mul_v2_v2(outset_uv[0], ibuf_inv);
01121                 mul_v2_v2(outset_uv[1], ibuf_inv);
01122                 mul_v2_v2(outset_uv[2], ibuf_inv);
01123                 mul_v2_v2(outset_uv[3], ibuf_inv);
01124         }
01125         else {
01126                 sub_v2_v2v2(no1, dir3, dir1);
01127                 sub_v2_v2v2(no2, dir1, dir2);
01128                 sub_v2_v2v2(no3, dir2, dir3);
01129                 normalize_v2(no1);
01130                 normalize_v2(no2);
01131                 normalize_v2(no3);
01132                 mul_v2_fl(no1, a1*scaler);
01133                 mul_v2_fl(no2, a2*scaler);
01134                 mul_v2_fl(no3, a3*scaler);
01135                 add_v2_v2v2(outset_uv[0], puv[0], no1);
01136                 add_v2_v2v2(outset_uv[1], puv[1], no2);
01137                 add_v2_v2v2(outset_uv[2], puv[2], no3);
01138 
01139                 mul_v2_v2(outset_uv[0], ibuf_inv);
01140                 mul_v2_v2(outset_uv[1], ibuf_inv);
01141                 mul_v2_v2(outset_uv[2], ibuf_inv);
01142         }
01143 }
01144 
01145 /* 
01146  * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4
01147  * 1<<i - where i is (0-3) 
01148  * 
01149  * If we're multithreadng, make sure threads are locked when this is called
01150  */
01151 static void project_face_seams_init(const ProjPaintState *ps, const int face_index, const int is_quad)
01152 {
01153         int other_face, other_fidx; /* vars for the other face, we also set its flag */
01154         int fidx1 = is_quad ? 3 : 2;
01155         int fidx2 = 0; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */
01156         
01157         do {
01158                 if ((ps->faceSeamFlags[face_index] & (1<<fidx1|16<<fidx1)) == 0) {
01159                         if (check_seam(ps, face_index, fidx1, fidx2, &other_face, &other_fidx)) {
01160                                 ps->faceSeamFlags[face_index] |= 1<<fidx1;
01161                                 if (other_face != -1)
01162                                         ps->faceSeamFlags[other_face] |= 1<<other_fidx;
01163                         }
01164                         else {
01165                                 ps->faceSeamFlags[face_index] |= 16<<fidx1;
01166                                 if (other_face != -1)
01167                                         ps->faceSeamFlags[other_face] |= 16<<other_fidx; /* second 4 bits for disabled */
01168                         }
01169                 }
01170                 
01171                 fidx2 = fidx1;
01172         } while (fidx1--);
01173 }
01174 #endif // PROJ_DEBUG_NOSEAMBLEED
01175 
01176 
01177 /* Converts a UV location to a 3D screenspace location
01178  * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo
01179  * 
01180  * This is used for finding a pixels location in screenspace for painting */
01181 static void screen_px_from_ortho(
01182                 float uv[2],
01183                 float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */
01184                 float uv1co[2], float uv2co[2], float uv3co[2],
01185                 float pixelScreenCo[4],
01186                 float w[3])
01187 {
01188         barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
01189         interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
01190 }
01191 
01192 /* same as screen_px_from_ortho except we need to take into account
01193  * the perspective W coord for each vert */
01194 static void screen_px_from_persp(
01195                 float uv[2],
01196                 float v1co[3], float v2co[3], float v3co[3], /* screenspace coords */
01197                 float uv1co[2], float uv2co[2], float uv3co[2],
01198                 float pixelScreenCo[4],
01199                 float w[3])
01200 {
01201 
01202         float wtot_inv, wtot;
01203         barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w);
01204         
01205         /* re-weight from the 4th coord of each screen vert */
01206         w[0] *= v1co[3];
01207         w[1] *= v2co[3];
01208         w[2] *= v3co[3];
01209         
01210         wtot = w[0]+w[1]+w[2];
01211         
01212         if (wtot > 0.0f) {
01213                 wtot_inv = 1.0f / wtot;
01214                 w[0] *= wtot_inv;
01215                 w[1] *= wtot_inv;
01216                 w[2] *= wtot_inv;
01217         }
01218         else {
01219                 w[0] = w[1] = w[2] = 1.0f/3.0f; /* dummy values for zero area face */
01220         }
01221         /* done re-weighting */
01222         
01223         interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w);
01224 }
01225 
01226 static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4])
01227 {
01228         float *uvCo1, *uvCo2, *uvCo3;
01229         float uv_other[2], x, y;
01230         
01231         uvCo1 =  (float *)tf_other->uv[0];
01232         if (side==1) {
01233                 uvCo2 =  (float *)tf_other->uv[2];
01234                 uvCo3 =  (float *)tf_other->uv[3];
01235         }
01236         else {
01237                 uvCo2 =  (float *)tf_other->uv[1];
01238                 uvCo3 =  (float *)tf_other->uv[2];
01239         }
01240         
01241         interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float*)w);
01242         
01243         /* use */
01244         uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y);
01245         
01246         
01247         if (ibuf_other->rect_float) { /* from float to float */
01248                 bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y);
01249         }
01250         else { /* from char to float */
01251                 bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y);
01252         }
01253                 
01254 }
01255 
01256 /* run this outside project_paint_uvpixel_init since pixels with mask 0 dont need init */
01257 static float project_paint_uvpixel_mask(
01258                 const ProjPaintState *ps,
01259                 const int face_index,
01260                 const int side,
01261                 const float w[3])
01262 {
01263         float mask;
01264         
01265         /* Image Mask */
01266         if (ps->do_layer_stencil) {
01267                 /* another UV layers image is masking this one's */
01268                 ImBuf *ibuf_other;
01269                 const MTFace *tf_other = ps->dm_mtface_stencil + face_index;
01270                 
01271                 if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) {
01272                         /* BKE_image_get_ibuf - TODO - this may be slow */
01273                         unsigned char rgba_ub[4];
01274                         float rgba_f[4];
01275                         
01276                         project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f);
01277                         
01278                         if (ibuf_other->rect_float) { /* from float to float */
01279                                 mask = ((rgba_f[0]+rgba_f[1]+rgba_f[2])/3.0f) * rgba_f[3];
01280                         }
01281                         else { /* from char to float */
01282                                 mask = ((rgba_ub[0]+rgba_ub[1]+rgba_ub[2])/(256*3.0f)) * (rgba_ub[3]/256.0f);
01283                         }
01284                         
01285                         if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */
01286                                 mask = (1.0f - mask);
01287 
01288                         if (mask == 0.0f) {
01289                                 return 0.0f;
01290                         }
01291                 }
01292                 else {
01293                         return 0.0f;
01294                 }
01295         } else {
01296                 mask = 1.0f;
01297         }
01298         
01299         /* calculate mask */
01300         if (ps->do_mask_normal) {
01301                 MFace *mf = ps->dm_mface + face_index;
01302                 short *no1, *no2, *no3;
01303                 float no[3], angle;
01304                 no1 = ps->dm_mvert[mf->v1].no;
01305                 if (side==1) {
01306                         no2 = ps->dm_mvert[mf->v3].no;
01307                         no3 = ps->dm_mvert[mf->v4].no;
01308                 }
01309                 else {
01310                         no2 = ps->dm_mvert[mf->v2].no;
01311                         no3 = ps->dm_mvert[mf->v3].no;
01312                 }
01313                 
01314                 no[0] = w[0]*no1[0] + w[1]*no2[0] + w[2]*no3[0];
01315                 no[1] = w[0]*no1[1] + w[1]*no2[1] + w[2]*no3[1];
01316                 no[2] = w[0]*no1[2] + w[1]*no2[2] + w[2]*no3[2];
01317                 normalize_v3(no);
01318                 
01319                 /* now we can use the normal as a mask */
01320                 if (ps->is_ortho) {
01321                         angle = angle_normalized_v3v3((float *)ps->viewDir, no);
01322                 }
01323                 else {
01324                         /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
01325                         float viewDirPersp[3];
01326                         float *co1, *co2, *co3;
01327                         co1 = ps->dm_mvert[mf->v1].co;
01328                         if (side==1) {
01329                                 co2 = ps->dm_mvert[mf->v3].co;
01330                                 co3 = ps->dm_mvert[mf->v4].co;
01331                         }
01332                         else {
01333                                 co2 = ps->dm_mvert[mf->v2].co;
01334                                 co3 = ps->dm_mvert[mf->v3].co;
01335                         }
01336 
01337                         /* Get the direction from the viewPoint to the pixel and normalize */
01338                         viewDirPersp[0] = (ps->viewPos[0] - (w[0]*co1[0] + w[1]*co2[0] + w[2]*co3[0]));
01339                         viewDirPersp[1] = (ps->viewPos[1] - (w[0]*co1[1] + w[1]*co2[1] + w[2]*co3[1]));
01340                         viewDirPersp[2] = (ps->viewPos[2] - (w[0]*co1[2] + w[1]*co2[2] + w[2]*co3[2]));
01341                         normalize_v3(viewDirPersp);
01342                         
01343                         angle = angle_normalized_v3v3(viewDirPersp, no);
01344                 }
01345                 
01346                 if (angle >= ps->normal_angle) {
01347                         return 0.0f; /* outsize the normal limit*/
01348                 }
01349                 else if (angle > ps->normal_angle_inner) {
01350                         mask *= (ps->normal_angle - angle) / ps->normal_angle_range;
01351                 } /* otherwise no mask normal is needed, were within the limit */
01352         }
01353         
01354         // This only works when the opacity dosnt change while painting, stylus pressure messes with this
01355         // so dont use it.
01356         // if (ps->is_airbrush==0) mask *= brush_alpha(ps->brush);
01357         
01358         return mask;
01359 }
01360 
01361 /* run this function when we know a bucket's, face's pixel can be initialized,
01362  * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */
01363 static ProjPixel *project_paint_uvpixel_init(
01364                 const ProjPaintState *ps,
01365                 MemArena *arena,
01366                 const ImBuf *ibuf,
01367                 short x_px, short y_px,
01368                 const float mask,
01369                 const int face_index,
01370                 const int image_index,
01371                 const float pixelScreenCo[4],
01372                 const int side,
01373                 const float w[3])
01374 {
01375         ProjPixel *projPixel;
01376         short size;
01377         
01378         /* wrap pixel location */
01379         x_px = x_px % ibuf->x;
01380         if (x_px<0) x_px += ibuf->x;
01381         y_px = y_px % ibuf->y;
01382         if (y_px<0) y_px += ibuf->y;
01383         
01384         if (ps->tool==PAINT_TOOL_CLONE) {
01385                 size = sizeof(ProjPixelClone);
01386         }
01387         else if (ps->tool==PAINT_TOOL_SMEAR) {
01388                 size = sizeof(ProjPixelClone);
01389         }
01390         else {
01391                 size = sizeof(ProjPixel);
01392         }
01393         
01394         projPixel = (ProjPixel *)BLI_memarena_alloc(arena, size);
01395         //memset(projPixel, 0, size);
01396         
01397         if (ibuf->rect_float) {
01398                 projPixel->pixel.f_pt = (float *)ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4);
01399                 projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0];  
01400                 projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1];  
01401                 projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2];  
01402                 projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3];  
01403         }
01404         else {
01405                 projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4));
01406                 projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt;
01407         }
01408         
01409         /* screenspace unclamped, we could keep its z and w values but dont need them at the moment */
01410         VECCOPY2D(projPixel->projCoSS, pixelScreenCo);
01411         
01412         projPixel->x_px = x_px;
01413         projPixel->y_px = y_px;
01414         
01415         projPixel->mask = (unsigned short)(mask * 65535);
01416         projPixel->mask_max = 0;
01417         
01418         /* which bounding box cell are we in?, needed for undo */
01419         projPixel->bb_cell_index = ((int)(((float)x_px/(float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + ((int)(((float)y_px/(float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV ;
01420         
01421         /* done with view3d_project_float inline */
01422         if (ps->tool==PAINT_TOOL_CLONE) {
01423                 if (ps->dm_mtface_clone) {
01424                         ImBuf *ibuf_other;
01425                         const MTFace *tf_other = ps->dm_mtface_clone + face_index;
01426                         
01427                         if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf(tf_other->tpage, NULL))) {
01428                                 /* BKE_image_get_ibuf - TODO - this may be slow */
01429                                 
01430                                 if (ibuf->rect_float) {
01431                                         if (ibuf_other->rect_float) { /* from float to float */
01432                                                 project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f);
01433                                         }
01434                                         else { /* from char to float */
01435                                                 unsigned char rgba_ub[4];
01436                                                 project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL);
01437                                                 IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub);
01438                                         }
01439                                 }
01440                                 else {
01441                                         if (ibuf_other->rect_float) { /* float to char */
01442                                                 float rgba[4];
01443                                                 project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba);
01444                                                 IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba)
01445                                         }
01446                                         else { /* char to char */
01447                                                 project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL);
01448                                         }
01449                                 }
01450                         }
01451                         else {
01452                                 if (ibuf->rect_float) {
01453                                         ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0;
01454                                 }
01455                                 else {
01456                                         ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0;
01457                                 }
01458                         }
01459                         
01460                 }
01461                 else {
01462                         float co[2];
01463                         sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset);
01464                         
01465                         /* no need to initialize the bucket, we're only checking buckets faces and for this
01466                          * the faces are already initialized in project_paint_delayed_face_init(...) */
01467                         if (ibuf->rect_float) {
01468                                 if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) {
01469                                         ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */
01470                                 }
01471                         }
01472                         else {
01473                                 if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) {
01474                                         ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */
01475                                 }
01476                         }
01477                 }
01478         }
01479         
01480 #ifdef PROJ_DEBUG_PAINT
01481         if (ibuf->rect_float)   projPixel->pixel.f_pt[0] = 0;
01482         else                                    projPixel->pixel.ch_pt[0] = 0;
01483 #endif
01484         projPixel->image_index = image_index;
01485         
01486         return projPixel;
01487 }
01488 
01489 static int line_clip_rect2f(
01490                 rctf *rect,
01491                 const float l1[2], const float l2[2],
01492                 float l1_clip[2], float l2_clip[2])
01493 {
01494         /* first account for horizontal, then vertical lines */
01495         /* horiz */
01496         if (fabsf(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) {
01497                 /* is the line out of range on its Y axis? */
01498                 if (l1[1] < rect->ymin || l1[1] > rect->ymax) {
01499                         return 0;
01500                 }
01501                 /* line is out of range on its X axis */
01502                 if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) {
01503                         return 0;
01504                 }
01505                 
01506                 
01507                 if (fabsf(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
01508                         if (BLI_in_rctf(rect, l1[0], l1[1])) {
01509                                 VECCOPY2D(l1_clip, l1);
01510                                 VECCOPY2D(l2_clip, l2);
01511                                 return 1;
01512                         }
01513                         else {
01514                                 return 0;
01515                         }
01516                 }
01517                 
01518                 VECCOPY2D(l1_clip, l1);
01519                 VECCOPY2D(l2_clip, l2);
01520                 CLAMP(l1_clip[0], rect->xmin, rect->xmax);
01521                 CLAMP(l2_clip[0], rect->xmin, rect->xmax);
01522                 return 1;
01523         }
01524         else if (fabsf(l1[0]-l2[0]) < PROJ_GEOM_TOLERANCE) {
01525                 /* is the line out of range on its X axis? */
01526                 if (l1[0] < rect->xmin || l1[0] > rect->xmax) {
01527                         return 0;
01528                 }
01529                 
01530                 /* line is out of range on its Y axis */
01531                 if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) {
01532                         return 0;
01533                 }
01534                 
01535                 if (fabsf(l1[1]-l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point  (or close to)*/
01536                         if (BLI_in_rctf(rect, l1[0], l1[1])) {
01537                                 VECCOPY2D(l1_clip, l1);
01538                                 VECCOPY2D(l2_clip, l2);
01539                                 return 1;
01540                         }
01541                         else {
01542                                 return 0;
01543                         }
01544                 }
01545                 
01546                 VECCOPY2D(l1_clip, l1);
01547                 VECCOPY2D(l2_clip, l2);
01548                 CLAMP(l1_clip[1], rect->ymin, rect->ymax);
01549                 CLAMP(l2_clip[1], rect->ymin, rect->ymax);
01550                 return 1;
01551         }
01552         else {
01553                 float isect;
01554                 short ok1 = 0;
01555                 short ok2 = 0;
01556                 
01557                 /* Done with vertical lines */
01558                 
01559                 /* are either of the points inside the rectangle ? */
01560                 if (BLI_in_rctf(rect, l1[0], l1[1])) {
01561                         VECCOPY2D(l1_clip, l1);
01562                         ok1 = 1;
01563                 }
01564                 
01565                 if (BLI_in_rctf(rect, l2[0], l2[1])) {
01566                         VECCOPY2D(l2_clip, l2);
01567                         ok2 = 1;
01568                 }
01569                 
01570                 /* line inside rect */
01571                 if (ok1 && ok2) return 1;
01572                 
01573                 /* top/bottom */
01574                 if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
01575                         if (l1[1] < l2[1]) { /* line 1 is outside */
01576                                 l1_clip[0] = isect;
01577                                 l1_clip[1] = rect->ymin;
01578                                 ok1 = 1;
01579                         }
01580                         else {
01581                                 l2_clip[0] = isect;
01582                                 l2_clip[1] = rect->ymin;
01583                                 ok2 = 2;
01584                         }
01585                 }
01586                 
01587                 if (ok1 && ok2) return 1;
01588                 
01589                 if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) {
01590                         if (l1[1] > l2[1]) { /* line 1 is outside */
01591                                 l1_clip[0] = isect;
01592                                 l1_clip[1] = rect->ymax;
01593                                 ok1 = 1;
01594                         }
01595                         else {
01596                                 l2_clip[0] = isect;
01597                                 l2_clip[1] = rect->ymax;
01598                                 ok2 = 2;
01599                         }
01600                 }
01601                 
01602                 if (ok1 && ok2) return 1;
01603                 
01604                 /* left/right */
01605                 if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
01606                         if (l1[0] < l2[0]) { /* line 1 is outside */
01607                                 l1_clip[0] = rect->xmin;
01608                                 l1_clip[1] = isect;
01609                                 ok1 = 1;
01610                         }
01611                         else {
01612                                 l2_clip[0] = rect->xmin;
01613                                 l2_clip[1] = isect;
01614                                 ok2 = 2;
01615                         }
01616                 }
01617         
01618                 if (ok1 && ok2) return 1;
01619                 
01620                 if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) {
01621                         if (l1[0] > l2[0]) { /* line 1 is outside */
01622                                 l1_clip[0] = rect->xmax;
01623                                 l1_clip[1] = isect;
01624                                 ok1 = 1;
01625                         }
01626                         else {
01627                                 l2_clip[0] = rect->xmax;
01628                                 l2_clip[1] = isect;
01629                                 ok2 = 2;
01630                         }
01631                 }
01632                 
01633                 if (ok1 && ok2) {
01634                         return 1;
01635                 }
01636                 else {
01637                         return 0;
01638                 }
01639         }
01640 }
01641 
01642 
01643 
01644 /* scale the quad & tri about its center
01645  * scaling by PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the
01646  * edge of the face but slightly inside it occlusion tests dont return hits on adjacent faces */
01647 #ifndef PROJ_DEBUG_NOSEAMBLEED
01648 static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset)
01649 {
01650         float cent[3];
01651         cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) / 4.0f;
01652         cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f;
01653         cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 4.0f;
01654         
01655         sub_v3_v3v3(insetCos[0], origCos[0], cent);
01656         sub_v3_v3v3(insetCos[1], origCos[1], cent);
01657         sub_v3_v3v3(insetCos[2], origCos[2], cent);
01658         sub_v3_v3v3(insetCos[3], origCos[3], cent);
01659         
01660         mul_v3_fl(insetCos[0], inset);
01661         mul_v3_fl(insetCos[1], inset);
01662         mul_v3_fl(insetCos[2], inset);
01663         mul_v3_fl(insetCos[3], inset);
01664         
01665         add_v3_v3(insetCos[0], cent);
01666         add_v3_v3(insetCos[1], cent);
01667         add_v3_v3(insetCos[2], cent);
01668         add_v3_v3(insetCos[3], cent);
01669 }
01670 
01671 
01672 static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset)
01673 {
01674         float cent[3];
01675         cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f;
01676         cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f;
01677         cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.0f;
01678         
01679         sub_v3_v3v3(insetCos[0], origCos[0], cent);
01680         sub_v3_v3v3(insetCos[1], origCos[1], cent);
01681         sub_v3_v3v3(insetCos[2], origCos[2], cent);
01682         
01683         mul_v3_fl(insetCos[0], inset);
01684         mul_v3_fl(insetCos[1], inset);
01685         mul_v3_fl(insetCos[2], inset);
01686         
01687         add_v3_v3(insetCos[0], cent);
01688         add_v3_v3(insetCos[1], cent);
01689         add_v3_v3(insetCos[2], cent);
01690 }
01691 #endif //PROJ_DEBUG_NOSEAMBLEED
01692 
01693 static float Vec2Lenf_nosqrt(const float *v1, const float *v2)
01694 {
01695         float x, y;
01696 
01697         x = v1[0]-v2[0];
01698         y = v1[1]-v2[1];
01699         return x*x+y*y;
01700 }
01701 
01702 static float Vec2Lenf_nosqrt_other(const float *v1, const float v2_1, const float v2_2)
01703 {
01704         float x, y;
01705 
01706         x = v1[0]-v2_1;
01707         y = v1[1]-v2_2;
01708         return x*x+y*y;
01709 }
01710 
01711 /* note, use a squared value so we can use Vec2Lenf_nosqrt
01712  * be sure that you have done a bounds check first or this may fail */
01713 /* only give bucket_bounds as an arg because we need it elsewhere */
01714 static int project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds)
01715 {
01716          
01717         /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect 
01718          * so we only need to test if the center is inside the vertical or horizontal bounds on either axis,
01719          * this is even less work then an intersection test
01720          * 
01721         if (BLI_in_rctf(bucket_bounds, cent[0], cent[1]))
01722                 return 1;
01723          */
01724         
01725         if((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) || (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1]) ) {
01726                 return 1;
01727         }
01728         
01729         /* out of bounds left */
01730         if (cent[0] < bucket_bounds->xmin) {
01731                 /* lower left out of radius test */
01732                 if (cent[1] < bucket_bounds->ymin) {
01733                         return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
01734                 } 
01735                 /* top left test */
01736                 else if (cent[1] > bucket_bounds->ymax) {
01737                         return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
01738                 }
01739         }
01740         else if (cent[0] > bucket_bounds->xmax) {
01741                 /* lower right out of radius test */
01742                 if (cent[1] < bucket_bounds->ymin) {
01743                         return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0;
01744                 } 
01745                 /* top right test */
01746                 else if (cent[1] > bucket_bounds->ymax) {
01747                         return (Vec2Lenf_nosqrt_other(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0;
01748                 }
01749         }
01750         
01751         return 0;
01752 }
01753 
01754 
01755 
01756 /* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp()
01757  * in ortho view this function gives good results when bucket_bounds are outside the triangle
01758  * however in some cases, perspective view will mess up with faces that have minimal screenspace area (viewed from the side)
01759  * 
01760  * for this reason its not relyable in this case so we'll use the Simple Barycentric' funcs that only account for points inside the triangle.
01761  * however switching back to this for ortho is always an option */
01762 
01763 static void rect_to_uvspace_ortho(
01764                 rctf *bucket_bounds,
01765                 float *v1coSS, float *v2coSS, float *v3coSS,
01766                 float *uv1co, float *uv2co, float *uv3co,
01767                 float bucket_bounds_uv[4][2],
01768                 const int flip)
01769 {
01770         float uv[2];
01771         float w[3];
01772         
01773         /* get the UV space bounding box */
01774         uv[0] = bucket_bounds->xmax;
01775         uv[1] = bucket_bounds->ymin;
01776         barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
01777         interp_v2_v2v2v2(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w);
01778 
01779         //uv[0] = bucket_bounds->xmax; // set above
01780         uv[1] = bucket_bounds->ymax;
01781         barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
01782         interp_v2_v2v2v2(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w);
01783 
01784         uv[0] = bucket_bounds->xmin;
01785         //uv[1] = bucket_bounds->ymax; // set above
01786         barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
01787         interp_v2_v2v2v2(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w);
01788 
01789         //uv[0] = bucket_bounds->xmin; // set above
01790         uv[1] = bucket_bounds->ymin;
01791         barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w);
01792         interp_v2_v2v2v2(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w);
01793 }
01794 
01795 /* same as above but use barycentric_weights_v2_persp */
01796 static void rect_to_uvspace_persp(
01797                 rctf *bucket_bounds,
01798                 float *v1coSS, float *v2coSS, float *v3coSS,
01799                 float *uv1co, float *uv2co, float *uv3co,
01800                 float bucket_bounds_uv[4][2],
01801                 const int flip
01802         )
01803 {
01804         float uv[2];
01805         float w[3];
01806         
01807         /* get the UV space bounding box */
01808         uv[0] = bucket_bounds->xmax;
01809         uv[1] = bucket_bounds->ymin;
01810         barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
01811         interp_v2_v2v2v2(bucket_bounds_uv[flip?3:0], uv1co, uv2co, uv3co, w);
01812 
01813         //uv[0] = bucket_bounds->xmax; // set above
01814         uv[1] = bucket_bounds->ymax;
01815         barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
01816         interp_v2_v2v2v2(bucket_bounds_uv[flip?2:1], uv1co, uv2co, uv3co, w);
01817 
01818         uv[0] = bucket_bounds->xmin;
01819         //uv[1] = bucket_bounds->ymax; // set above
01820         barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
01821         interp_v2_v2v2v2(bucket_bounds_uv[flip?1:2], uv1co, uv2co, uv3co, w);
01822 
01823         //uv[0] = bucket_bounds->xmin; // set above
01824         uv[1] = bucket_bounds->ymin;
01825         barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w);
01826         interp_v2_v2v2v2(bucket_bounds_uv[flip?0:3], uv1co, uv2co, uv3co, w);
01827 }
01828 
01829 /* This works as we need it to but we can save a few steps and not use it */
01830 
01831 #if 0
01832 static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2])
01833 {
01834         float v1[2], v2[2];
01835         
01836         v1[0] = p1[0]-p2[0];    v1[1] = p1[1]-p2[1];
01837         v2[0] = p3[0]-p2[0];    v2[1] = p3[1]-p2[1];
01838         
01839         return -atan2(v1[0]*v2[1] - v1[1]*v2[0], v1[0]*v2[0]+v1[1]*v2[1]);
01840 }
01841 #endif
01842 
01843 #define ISECT_1 (1)
01844 #define ISECT_2 (1<<1)
01845 #define ISECT_3 (1<<2)
01846 #define ISECT_4 (1<<3)
01847 #define ISECT_ALL3 ((1<<3)-1)
01848 #define ISECT_ALL4 ((1<<4)-1)
01849 
01850 /* limit must be a fraction over 1.0f */
01851 static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit)
01852 {
01853         return ((area_tri_v2(pt,v1,v2) + area_tri_v2(pt,v2,v3) + area_tri_v2(pt,v3,v1)) / (area_tri_v2(v1,v2,v3))) < limit;
01854 }
01855 
01856 /* Clip the face by a bucket and set the uv-space bucket_bounds_uv
01857  * so we have the clipped UV's to do pixel intersection tests with 
01858  * */
01859 static int float_z_sort_flip(const void *p1, const void *p2) {
01860         return (((float *)p1)[2] < ((float *)p2)[2] ? 1:-1);
01861 }
01862 
01863 static int float_z_sort(const void *p1, const void *p2) {
01864         return (((float *)p1)[2] < ((float *)p2)[2] ?-1:1);
01865 }
01866 
01867 static void project_bucket_clip_face(
01868                 const int is_ortho,
01869                 rctf *bucket_bounds,
01870                 float *v1coSS, float *v2coSS, float *v3coSS,
01871                 float *uv1co, float *uv2co, float *uv3co,
01872                 float bucket_bounds_uv[8][2],
01873                 int *tot)
01874 {
01875         int inside_bucket_flag = 0;
01876         int inside_face_flag = 0;
01877         const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f));
01878         
01879         float bucket_bounds_ss[4][2];
01880 
01881         /* get the UV space bounding box */
01882         inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v1coSS[0], v1coSS[1]);
01883         inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v2coSS[0], v2coSS[1])          << 1;
01884         inside_bucket_flag |= BLI_in_rctf(bucket_bounds, v3coSS[0], v3coSS[1])          << 2;
01885         
01886         if (inside_bucket_flag == ISECT_ALL3) {
01887                 /* all screenspace points are inside the bucket bounding box, this means we dont need to clip and can simply return the UVs */
01888                 if (flip) { /* facing the back? */
01889                         VECCOPY2D(bucket_bounds_uv[0], uv3co);
01890                         VECCOPY2D(bucket_bounds_uv[1], uv2co);
01891                         VECCOPY2D(bucket_bounds_uv[2], uv1co);
01892                 }
01893                 else {
01894                         VECCOPY2D(bucket_bounds_uv[0], uv1co);
01895                         VECCOPY2D(bucket_bounds_uv[1], uv2co);
01896                         VECCOPY2D(bucket_bounds_uv[2], uv3co);
01897                 }
01898                 
01899                 *tot = 3; 
01900                 return;
01901         }
01902         
01903         /* get the UV space bounding box */
01904         /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */
01905         bucket_bounds_ss[0][0] = bucket_bounds->xmax;
01906         bucket_bounds_ss[0][1] = bucket_bounds->ymin;
01907         inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0);
01908         
01909         bucket_bounds_ss[1][0] = bucket_bounds->xmax;
01910         bucket_bounds_ss[1][1] = bucket_bounds->ymax;
01911         inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0);
01912 
01913         bucket_bounds_ss[2][0] = bucket_bounds->xmin;
01914         bucket_bounds_ss[2][1] = bucket_bounds->ymax;
01915         inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0);
01916 
01917         bucket_bounds_ss[3][0] = bucket_bounds->xmin;
01918         bucket_bounds_ss[3][1] = bucket_bounds->ymin;
01919         inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1+PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0);
01920         
01921         if (inside_face_flag == ISECT_ALL4) {
01922                 /* bucket is totally inside the screenspace face, we can safely use weights */
01923                 
01924                 if (is_ortho)   rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
01925                 else                    rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip);
01926                 
01927                 *tot = 4;
01928                 return;
01929         }
01930         else {
01931                 /* The Complicated Case! 
01932                  * 
01933                  * The 2 cases above are where the face is inside the bucket or the bucket is inside the face.
01934                  * 
01935                  * we need to make a convex polyline from the intersection between the screenspace face
01936                  * and the bucket bounds.
01937                  * 
01938                  * There are a number of ways this could be done, currently it just collects all intersecting verts,
01939                  * and line intersections,  then sorts them clockwise, this is a lot easier then evaluating the geometry to
01940                  * do a correct clipping on both shapes. */
01941                 
01942                 
01943                 /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */
01944                 
01945                 
01946                 
01947                 /* Maximum possible 6 intersections when using a rectangle and triangle */
01948                 float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */
01949                 float v1_clipSS[2], v2_clipSS[2];
01950                 float w[3];
01951                 
01952                 /* calc center*/
01953                 float cent[2] = {0.0f, 0.0f};
01954                 /*float up[2] = {0.0f, 1.0f};*/
01955                 int i;
01956                 short doubles;
01957                 
01958                 (*tot) = 0;
01959                 
01960                 if (inside_face_flag & ISECT_1) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; }
01961                 if (inside_face_flag & ISECT_2) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; }
01962                 if (inside_face_flag & ISECT_3) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; }
01963                 if (inside_face_flag & ISECT_4) { VECCOPY2D(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; }
01964                 
01965                 if (inside_bucket_flag & ISECT_1) {     VECCOPY2D(isectVCosSS[*tot], v1coSS); (*tot)++; }
01966                 if (inside_bucket_flag & ISECT_2) {     VECCOPY2D(isectVCosSS[*tot], v2coSS); (*tot)++; }
01967                 if (inside_bucket_flag & ISECT_3) {     VECCOPY2D(isectVCosSS[*tot], v3coSS); (*tot)++; }
01968                 
01969                 if ((inside_bucket_flag & (ISECT_1|ISECT_2)) != (ISECT_1|ISECT_2)) {
01970                         if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) {
01971                                 if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
01972                                 if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
01973                         }
01974                 }
01975                 
01976                 if ((inside_bucket_flag & (ISECT_2|ISECT_3)) != (ISECT_2|ISECT_3)) {
01977                         if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) {
01978                                 if ((inside_bucket_flag & ISECT_2)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
01979                                 if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
01980                         }
01981                 }       
01982                 
01983                 if ((inside_bucket_flag & (ISECT_3|ISECT_1)) != (ISECT_3|ISECT_1)) {
01984                         if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) {
01985                                 if ((inside_bucket_flag & ISECT_3)==0) { VECCOPY2D(isectVCosSS[*tot], v1_clipSS); (*tot)++; }
01986                                 if ((inside_bucket_flag & ISECT_1)==0) { VECCOPY2D(isectVCosSS[*tot], v2_clipSS); (*tot)++; }
01987                         }
01988                 }
01989                 
01990                 
01991                 if ((*tot) < 3) { /* no intersections to speak of */
01992                         *tot = 0;
01993                         return;
01994                 }
01995         
01996                 /* now we have all points we need, collect their angles and sort them clockwise */
01997                 
01998                 for(i=0; i<(*tot); i++) {
01999                         cent[0] += isectVCosSS[i][0];
02000                         cent[1] += isectVCosSS[i][1];
02001                 }
02002                 cent[0] = cent[0] / (float)(*tot);
02003                 cent[1] = cent[1] / (float)(*tot);
02004                 
02005                 
02006                 
02007                 /* Collect angles for every point around the center point */
02008 
02009                 
02010 #if 0   /* uses a few more cycles then the above loop */
02011                 for(i=0; i<(*tot); i++) {
02012                         isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]);
02013                 }
02014 #endif
02015 
02016                 v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */
02017                 v1_clipSS[1] = cent[1] + 1.0f;
02018                 
02019                 for(i=0; i<(*tot); i++) {
02020                         v2_clipSS[0] = isectVCosSS[i][0] - cent[0];
02021                         v2_clipSS[1] = isectVCosSS[i][1] - cent[1];
02022                         isectVCosSS[i][2] = atan2f(v1_clipSS[0]*v2_clipSS[1] - v1_clipSS[1]*v2_clipSS[0], v1_clipSS[0]*v2_clipSS[0]+v1_clipSS[1]*v2_clipSS[1]); 
02023                 }
02024                 
02025                 if (flip)       qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort_flip);
02026                 else            qsort(isectVCosSS, *tot, sizeof(float)*3, float_z_sort);
02027                 
02028                 /* remove doubles */
02029                 /* first/last check */
02030                 if (fabsf(isectVCosSS[0][0]-isectVCosSS[(*tot)-1][0]) < PROJ_GEOM_TOLERANCE &&  fabsf(isectVCosSS[0][1]-isectVCosSS[(*tot)-1][1]) < PROJ_GEOM_TOLERANCE) {
02031                         (*tot)--;
02032                 }
02033                 
02034                 /* its possible there is only a few left after remove doubles */
02035                 if ((*tot) < 3) {
02036                         // printf("removed too many doubles A\n");
02037                         *tot = 0;
02038                         return;
02039                 }
02040                 
02041                 doubles = TRUE;
02042                 while (doubles==TRUE) {
02043                         doubles = FALSE;
02044                         for(i=1; i<(*tot); i++) {
02045                                 if (fabsf(isectVCosSS[i-1][0]-isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE &&
02046                                         fabsf(isectVCosSS[i-1][1]-isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE)
02047                                 {
02048                                         int j;
02049                                         for(j=i+1; j<(*tot); j++) {
02050                                                 isectVCosSS[j-1][0] = isectVCosSS[j][0]; 
02051                                                 isectVCosSS[j-1][1] = isectVCosSS[j][1]; 
02052                                         }
02053                                         doubles = TRUE; /* keep looking for more doubles */
02054                                         (*tot)--;
02055                                 }
02056                         }
02057                 }
02058                 
02059                 /* its possible there is only a few left after remove doubles */
02060                 if ((*tot) < 3) {
02061                         // printf("removed too many doubles B\n");
02062                         *tot = 0;
02063                         return;
02064                 }
02065                 
02066                 
02067                 if (is_ortho) {
02068                         for(i=0; i<(*tot); i++) {
02069                                 barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
02070                                 interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
02071                         }
02072                 }
02073                 else {
02074                         for(i=0; i<(*tot); i++) {
02075                                 barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w);
02076                                 interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w);
02077                         }
02078                 }
02079         }
02080 
02081 #ifdef PROJ_DEBUG_PRINT_CLIP
02082         /* include this at the bottom of the above function to debug the output */
02083 
02084         {
02085                 /* If there are ever any problems, */
02086                 float test_uv[4][2];
02087                 int i;
02088                 if (is_ortho)   rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
02089                 else                            rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip);
02090                 printf("(  [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1],   test_uv[1][0], test_uv[1][1],    test_uv[2][0], test_uv[2][1],    test_uv[3][0], test_uv[3][1]);
02091                 
02092                 printf("  [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1],   uv2co[0], uv2co[1],    uv3co[0], uv3co[1]);
02093                 
02094                 printf("[");
02095                 for (i=0; i < (*tot); i++) {
02096                         printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]);
02097                 }
02098                 printf("]),\\\n");
02099         }
02100 #endif
02101 }
02102 
02103         /*
02104 # This script creates faces in a blender scene from printed data above.
02105 
02106 project_ls = [
02107 ...(output from above block)...
02108 ]
02109  
02110 from Blender import Scene, Mesh, Window, sys, Mathutils
02111 
02112 import bpy
02113 
02114 V = Mathutils.Vector
02115 
02116 def main():
02117         sce = bpy.data.scenes.active
02118         
02119         for item in project_ls:
02120                 bb = item[0]
02121                 uv = item[1]
02122                 poly = item[2]
02123                 
02124                 me = bpy.data.meshes.new()
02125                 ob = sce.objects.new(me)
02126                 
02127                 me.verts.extend([V(bb[0]).resize3D(), V(bb[1]).resize3D(), V(bb[2]).resize3D(), V(bb[3]).resize3D()])
02128                 me.faces.extend([(0,1,2,3),])
02129                 me.verts.extend([V(uv[0]).resize3D(), V(uv[1]).resize3D(), V(uv[2]).resize3D()])
02130                 me.faces.extend([(4,5,6),])
02131                 
02132                 vs = [V(p).resize3D() for p in poly]
02133                 print len(vs)
02134                 l = len(me.verts)
02135                 me.verts.extend(vs)
02136                 
02137                 i = l
02138                 while i < len(me.verts):
02139                         ii = i+1
02140                         if ii==len(me.verts):
02141                                 ii = l
02142                         me.edges.extend([i, ii])
02143                         i+=1
02144 
02145 if __name__ == '__main__':
02146         main()
02147  */     
02148 
02149 
02150 #undef ISECT_1
02151 #undef ISECT_2
02152 #undef ISECT_3
02153 #undef ISECT_4
02154 #undef ISECT_ALL3
02155 #undef ISECT_ALL4
02156 
02157         
02158 /* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise
02159  * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */
02160 static int IsectPoly2Df(const float pt[2], float uv[][2], const int tot)
02161 {
02162         int i;
02163         if (line_point_side_v2(uv[tot-1], uv[0], pt) < 0.0f)
02164                 return 0;
02165         
02166         for (i=1; i<tot; i++) {
02167                 if (line_point_side_v2(uv[i-1], uv[i], pt) < 0.0f)
02168                         return 0;
02169                 
02170         }
02171         
02172         return 1;
02173 }
02174 static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot)
02175 {
02176         int i;
02177         int side = (line_point_side_v2(uv[tot-1], uv[0], pt) > 0.0f);
02178         
02179         for (i=1; i<tot; i++) {
02180                 if ((line_point_side_v2(uv[i-1], uv[i], pt) > 0.0f) != side)
02181                         return 0;
02182                 
02183         }
02184         
02185         return 1;
02186 }
02187 
02188 /* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket.
02189  * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */
02190 static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v)
02191 {
02192         /* Projection vars, to get the 3D locations into screen space  */
02193         MemArena *arena = ps->arena_mt[thread_index];
02194         LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index;
02195         LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index];
02196         
02197         const MFace *mf = ps->dm_mface + face_index;
02198         const MTFace *tf = ps->dm_mtface + face_index;
02199         
02200         /* UV/pixel seeking data */
02201         int x; /* Image X-Pixel */
02202         int y;/* Image Y-Pixel */
02203         float mask;
02204         float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */
02205         
02206         int side;
02207         float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */
02208         
02209         float *vCo[4]; /* vertex screenspace coords */
02210         
02211         float w[3], wco[3];
02212         
02213         float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */
02214         float pixelScreenCo[4];
02215         
02216         rcti bounds_px; /* ispace bounds */
02217         /* vars for getting uvspace bounds */
02218         
02219         float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face,  */
02220         float xhalfpx, yhalfpx;
02221         const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y;
02222         
02223         int has_x_isect = 0, has_isect = 0; /* for early loop exit */
02224         
02225         int i1, i2, i3;
02226         
02227         float uv_clip[8][2];
02228         int uv_clip_tot;
02229         const short is_ortho = ps->is_ortho;
02230         const short do_backfacecull = ps->do_backfacecull;
02231         const short do_clip= ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
02232         
02233         vCo[0] = ps->dm_mvert[mf->v1].co;
02234         vCo[1] = ps->dm_mvert[mf->v2].co;
02235         vCo[2] = ps->dm_mvert[mf->v3].co;
02236         
02237         
02238         /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel
02239          * this is done so we can avoid offseting all the pixels by 0.5 which causes
02240          * problems when wrapping negative coords */
02241         xhalfpx = (0.5f+   (PROJ_GEOM_TOLERANCE/3.0f)   ) / ibuf_xf;
02242         yhalfpx = (0.5f+   (PROJ_GEOM_TOLERANCE/4.0f)   ) / ibuf_yf;
02243         
02244         /* Note about (PROJ_GEOM_TOLERANCE/x) above...
02245           Needed to add this offset since UV coords are often quads aligned to pixels.
02246           In this case pixels can be exactly between 2 triangles causing nasty
02247           artifacts.
02248           
02249           This workaround can be removed and painting will still work on most cases
02250           but since the first thing most people try is painting onto a quad- better make it work.
02251          */
02252 
02253 
02254 
02255         tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx;
02256         tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx;
02257 
02258         tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx;
02259         tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx;
02260         
02261         tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx;
02262         tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx;  
02263         
02264         if (mf->v4) {
02265                 vCo[3] = ps->dm_mvert[ mf->v4 ].co;
02266                 
02267                 tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx;
02268                 tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx;
02269                 side = 1;
02270         }
02271         else {
02272                 side = 0;
02273         }
02274         
02275         do {
02276                 if (side==1) {
02277                         i1=0; i2=2; i3=3;
02278                 }
02279                 else {
02280                         i1=0; i2=1; i3=2;
02281                 }
02282                 
02283                 uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1];
02284                 uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2];
02285                 uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3];
02286 
02287                 v1coSS = ps->screenCoords[ (*(&mf->v1 + i1)) ];
02288                 v2coSS = ps->screenCoords[ (*(&mf->v1 + i2)) ];
02289                 v3coSS = ps->screenCoords[ (*(&mf->v1 + i3)) ];
02290                 
02291                 /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/
02292                 project_bucket_clip_face(
02293                                 is_ortho, bucket_bounds,
02294                                 v1coSS, v2coSS, v3coSS,
02295                                 uv1co, uv2co, uv3co,
02296                                 uv_clip, &uv_clip_tot
02297                 );
02298 
02299                 /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */
02300                 /*
02301                 if (uv_clip_tot>6) {
02302                         printf("this should never happen! %d\n", uv_clip_tot);
02303                 }*/
02304                 
02305 
02306                 if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) {
02307 
02308                         if(clamp_u) {
02309                                 CLAMP(bounds_px.xmin, 0, ibuf->x);
02310                                 CLAMP(bounds_px.xmax, 0, ibuf->x);
02311                         }
02312 
02313                         if(clamp_v) {
02314                                 CLAMP(bounds_px.ymin, 0, ibuf->y);
02315                                 CLAMP(bounds_px.ymax, 0, ibuf->y);
02316                         }
02317 
02318                         /* clip face and */
02319                         
02320                         has_isect = 0;
02321                         for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
02322                                 //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
02323                                 uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */
02324 
02325                                 has_x_isect = 0;
02326                                 for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
02327                                         //uv[0] = (((float)x) + 0.5f) / ibuf->x;
02328                                         uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */
02329                                         
02330                                         /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work,
02331                                          * could check the poly direction but better to do this */
02332                                         if(     (do_backfacecull                && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) ||
02333                                                 (do_backfacecull==0             && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) {
02334                                                 
02335                                                 has_x_isect = has_isect = 1;
02336                                                 
02337                                                 if (is_ortho)   screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
02338                                                 else                    screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w);
02339                                                 
02340                                                 /* a pitty we need to get the worldspace pixel location here */
02341                                                 if(do_clip) {
02342                                                         interp_v3_v3v3v3(wco, ps->dm_mvert[ (*(&mf->v1 + i1)) ].co, ps->dm_mvert[ (*(&mf->v1 + i2)) ].co, ps->dm_mvert[ (*(&mf->v1 + i3)) ].co, w);
02343                                                         if(ED_view3d_test_clipping(ps->rv3d, wco, 1)) {
02344                                                                 continue; /* Watch out that no code below this needs to run */
02345                                                         }
02346                                                 }
02347                                                 
02348                                                 /* Is this UV visible from the view? - raytrace */
02349                                                 /* project_paint_PickFace is less complex, use for testing */
02350                                                 //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) {
02351                                                 if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) {
02352                                                         
02353                                                         mask = project_paint_uvpixel_mask(ps, face_index, side, w);
02354                                                         
02355                                                         if (mask > 0.0f) {
02356                                                                 BLI_linklist_prepend_arena(
02357                                                                         bucketPixelNodes,
02358                                                                         project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
02359                                                                         arena
02360                                                                 );
02361                                                         }
02362                                                 }
02363                                                 
02364                                         }
02365 //#if 0
02366                                         else if (has_x_isect) {
02367                                                 /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
02368                                                 break;
02369                                         }
02370 //#endif
02371                                 }
02372                                 
02373                                 
02374 #if 0                   /* TODO - investigate why this dosnt work sometimes! it should! */
02375                                 /* no intersection for this entire row, after some intersection above means we can quit now */
02376                                 if (has_x_isect==0 && has_isect) { 
02377                                         break;
02378                                 }
02379 #endif
02380                         }
02381                 }
02382         } while(side--);
02383 
02384         
02385         
02386 #ifndef PROJ_DEBUG_NOSEAMBLEED
02387         if (ps->seam_bleed_px > 0.0f) {
02388                 int face_seam_flag;
02389                 
02390                 if (ps->thread_tot > 1)
02391                         BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
02392                 
02393                 face_seam_flag = ps->faceSeamFlags[face_index];
02394                 
02395                 /* are any of our edges un-initialized? */
02396                 if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_NOSEAM1))==0 || 
02397                         (face_seam_flag & (PROJ_FACE_SEAM2|PROJ_FACE_NOSEAM2))==0 || 
02398                         (face_seam_flag & (PROJ_FACE_SEAM3|PROJ_FACE_NOSEAM3))==0 || 
02399                         (face_seam_flag & (PROJ_FACE_SEAM4|PROJ_FACE_NOSEAM4))==0
02400                 ) {
02401                         project_face_seams_init(ps, face_index, mf->v4);
02402                         face_seam_flag = ps->faceSeamFlags[face_index];
02403                         //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4);
02404                 }
02405                 
02406                 if ((face_seam_flag & (PROJ_FACE_SEAM1|PROJ_FACE_SEAM2|PROJ_FACE_SEAM3|PROJ_FACE_SEAM4))==0) {
02407                         
02408                         if (ps->thread_tot > 1)
02409                                 BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
02410                         
02411                 }
02412                 else {
02413                         /* we have a seam - deal with it! */
02414                         
02415                         /* Now create new UV's for the seam face */
02416                         float (*outset_uv)[2] = ps->faceSeamUVs[face_index];
02417                         float insetCos[4][3]; /* inset face coords.  NOTE!!! ScreenSace for ortho, Worldspace in prespective view */
02418 
02419                         float fac;
02420                         float *vCoSS[4]; /* vertex screenspace coords */
02421                         
02422                         float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */
02423                         float edge_verts_inset_clip[2][3];
02424                         int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */
02425                         
02426                         float seam_subsection[4][2];
02427                         float fac1, fac2, ftot;
02428                         
02429                         
02430                         if (outset_uv[0][0]==FLT_MAX) /* first time initialize */
02431                                 uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4);
02432                         
02433                         /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */
02434                         if (ps->thread_tot > 1)
02435                                 BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */
02436                         
02437                         vCoSS[0] = ps->screenCoords[mf->v1];
02438                         vCoSS[1] = ps->screenCoords[mf->v2];
02439                         vCoSS[2] = ps->screenCoords[mf->v3];
02440                         if (mf->v4)
02441                                 vCoSS[3] = ps->screenCoords[ mf->v4 ];
02442                         
02443                         /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */
02444                         if (is_ortho) {
02445                                 if (mf->v4)     scale_quad(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
02446                                 else            scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM);
02447                         }
02448                         else {
02449                                 if (mf->v4)     scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
02450                                 else            scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM);
02451                         }
02452                         
02453                         side = 0; /* for triangles this wont need to change */
02454                         
02455                         for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) {
02456                                 if (mf->v4)             fidx2 = (fidx1==3) ? 0 : fidx1+1; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) */
02457                                 else                    fidx2 = (fidx1==2) ? 0 : fidx1+1; /* next fidx in the face (0,1,2) -> (1,2,0) */
02458                                 
02459                                 if (    (face_seam_flag & (1<<fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */
02460                                                 line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])
02461                                 ) {
02462 
02463                                         ftot = len_v2v2(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */
02464                                         
02465                                         if (ftot > 0.0f) { /* avoid div by zero */
02466                                                 if (mf->v4) {
02467                                                         if (fidx1==2 || fidx2==2)       side= 1;
02468                                                         else                                            side= 0;
02469                                                 }
02470                                                 
02471                                                 fac1 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[0]) / ftot;
02472                                                 fac2 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[1]) / ftot;
02473                                                 
02474                                                 interp_v2_v2v2(seam_subsection[0], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac1);
02475                                                 interp_v2_v2v2(seam_subsection[1], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac2);
02476 
02477                                                 interp_v2_v2v2(seam_subsection[2], outset_uv[fidx1], outset_uv[fidx2], fac2);
02478                                                 interp_v2_v2v2(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1);
02479                                                 
02480                                                 /* if the bucket_clip_edges values Z values was kept we could avoid this
02481                                                  * Inset needs to be added so occlusion tests wont hit adjacent faces */
02482                                                 interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1);
02483                                                 interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2);
02484                                                 
02485 
02486                                                 if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, 1)) {
02487                                                         /* bounds between the seam rect and the uvspace bucket pixels */
02488                                                         
02489                                                         has_isect = 0;
02490                                                         for (y = bounds_px.ymin; y < bounds_px.ymax; y++) {
02491                                                                 // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y;
02492                                                                 uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */
02493                                                                 
02494                                                                 has_x_isect = 0;
02495                                                                 for (x = bounds_px.xmin; x < bounds_px.xmax; x++) {
02496                                                                         //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x;
02497                                                                         uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */
02498                                                                         
02499                                                                         /* test we're inside uvspace bucket and triangle bounds */
02500                                                                         if (isect_point_quad_v2(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) {
02501                                                                                 
02502                                                                                 /* We need to find the closest point along the face edge,
02503                                                                                  * getting the screen_px_from_*** wont work because our actual location
02504                                                                                  * is not relevent, since we are outside the face, Use VecLerpf to find
02505                                                                                  * our location on the side of the face's UV */
02506                                                                                 /*
02507                                                                                 if (is_ortho)   screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
02508                                                                                 else                                    screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo);
02509                                                                                 */
02510                                                                                 
02511                                                                                 /* Since this is a seam we need to work out where on the line this pixel is */
02512                                                                                 //fac = line_point_factor_v2(uv, uv_seam_quad[0], uv_seam_quad[1]);
02513                                                                                 
02514                                                                                 fac = line_point_factor_v2(uv, seam_subsection[0], seam_subsection[1]);
02515                                                                                 if (fac < 0.0f)         { VECCOPY(pixelScreenCo, edge_verts_inset_clip[0]); }
02516                                                                                 else if (fac > 1.0f)    { VECCOPY(pixelScreenCo, edge_verts_inset_clip[1]); }
02517                                                                                 else                            { interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); }
02518                                                                                 
02519                                                                                 if (!is_ortho) {
02520                                                                                         pixelScreenCo[3] = 1.0f;
02521                                                                                         mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */
02522                                                                                         pixelScreenCo[0] = (float)(ps->winx/2.0f)+(ps->winx/2.0f)*pixelScreenCo[0]/pixelScreenCo[3];
02523                                                                                         pixelScreenCo[1] = (float)(ps->winy/2.0f)+(ps->winy/2.0f)*pixelScreenCo[1]/pixelScreenCo[3];
02524                                                                                         pixelScreenCo[2] = pixelScreenCo[2]/pixelScreenCo[3]; /* Use the depth for bucket point occlusion */
02525                                                                                 }
02526                                                                                 
02527                                                                                 if (ps->do_occlude==0 || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) {
02528                                                                                         
02529                                                                                         /* Only bother calculating the weights if we intersect */
02530                                                                                         if (ps->do_mask_normal || ps->dm_mtface_clone) {
02531 #if 1
02532                                                                                                 /* get the UV on the line since we want to copy the pixels from there for bleeding */
02533                                                                                                 float uv_close[2];
02534                                                                                                 float fac= closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]);
02535                                                                                                 if              (fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]);
02536                                                                                                 else if (fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]);
02537 
02538                                                                                                 if (side) {
02539                                                                                                         barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv_close, w);
02540                                                                                                 }
02541                                                                                                 else {
02542                                                                                                         barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], uv_close, w);
02543                                                                                                 }
02544 #else                                                                                   /* this is buggy with quads, dont use for now */
02545 
02546                                                                                                 /* Cheat, we know where we are along the edge so work out the weights from that */
02547                                                                                                 fac = fac1 + (fac * (fac2-fac1));
02548 
02549                                                                                                 w[0]=w[1]=w[2]= 0.0;
02550                                                                                                 if (side) {
02551                                                                                                         w[fidx1?fidx1-1:0] = 1.0f-fac;
02552                                                                                                         w[fidx2?fidx2-1:0] = fac;
02553                                                                                                 }
02554                                                                                                 else {
02555                                                                                                         w[fidx1] = 1.0f-fac;
02556                                                                                                         w[fidx2] = fac;
02557                                                                                                 }
02558 #endif
02559                                                                                         }
02560                                                                                         
02561                                                                                         /* a pitty we need to get the worldspace pixel location here */
02562                                                                                         if(do_clip) {
02563                                                                                                 if (side)       interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w);
02564                                                                                                 else            interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w);
02565 
02566                                                                                                 if(ED_view3d_test_clipping(ps->rv3d, wco, 1)) {
02567                                                                                                         continue; /* Watch out that no code below this needs to run */
02568                                                                                                 }
02569                                                                                         }
02570                                                                                         
02571                                                                                         mask = project_paint_uvpixel_mask(ps, face_index, side, w);
02572                                                                                         
02573                                                                                         if (mask > 0.0f) {
02574                                                                                                 BLI_linklist_prepend_arena(
02575                                                                                                         bucketPixelNodes,
02576                                                                                                         project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w),
02577                                                                                                         arena
02578                                                                                                 );
02579                                                                                         }
02580                                                                                         
02581                                                                                 }
02582                                                                         }
02583                                                                         else if (has_x_isect) {
02584                                                                                 /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
02585                                                                                 break;
02586                                                                         }
02587                                                                 }
02588                                                                 
02589 #if 0                                                   /* TODO - investigate why this dosnt work sometimes! it should! */
02590                                                                 /* no intersection for this entire row, after some intersection above means we can quit now */
02591                                                                 if (has_x_isect==0 && has_isect) { 
02592                                                                         break;
02593                                                                 }
02594 #endif
02595                                                         }
02596                                                 }
02597                                         }
02598                                 }
02599                         }
02600                 }
02601         }
02602 #endif // PROJ_DEBUG_NOSEAMBLEED
02603 }
02604 
02605 
02606 /* takes floating point screenspace min/max and returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */
02607 static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2])
02608 {
02609         /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */
02610         /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f is always truncated to 1, is this really correct?? - jwilkins */
02611         bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f); /* these offsets of 0.5 and 1.5 seem odd but they are correct */
02612         bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f);
02613         
02614         bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f);
02615         bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f);
02616         
02617         /* incase the rect is outside the mesh 2d bounds */
02618         CLAMP(bucketMin[0], 0, ps->buckets_x);
02619         CLAMP(bucketMin[1], 0, ps->buckets_y);
02620         
02621         CLAMP(bucketMax[0], 0, ps->buckets_x);
02622         CLAMP(bucketMax[1], 0, ps->buckets_y);
02623 }
02624 
02625 /* set bucket_bounds to a screen space-aligned floating point bound-box */
02626 static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds)
02627 {
02628         bucket_bounds->xmin =   ps->screenMin[0]+((bucket_x)*(ps->screen_width / ps->buckets_x));               /* left */
02629         bucket_bounds->xmax =   ps->screenMin[0]+((bucket_x+1)*(ps->screen_width / ps->buckets_x));     /* right */
02630         
02631         bucket_bounds->ymin =   ps->screenMin[1]+((bucket_y)*(ps->screen_height / ps->buckets_y));              /* bottom */
02632         bucket_bounds->ymax =   ps->screenMin[1]+((bucket_y+1)*(ps->screen_height  / ps->buckets_y));   /* top */
02633 }
02634 
02635 /* Fill this bucket with pixels from the faces that intersect it.
02636  * 
02637  * have bucket_bounds as an argument so we don;t need to give bucket_x/y the rect function needs */
02638 static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds)
02639 {
02640         LinkNode *node;
02641         int face_index, image_index=0;
02642         ImBuf *ibuf = NULL;
02643         Image *ima = NULL;
02644         MTFace *tf;
02645         
02646         Image *tpage_last = NULL;
02647         
02648 
02649         if (ps->image_tot==1) {
02650                 /* Simple loop, no context switching */
02651                 ibuf = ps->projImages[0].ibuf;
02652                 ima = ps->projImages[0].ima;
02653 
02654                 for (node = ps->bucketFaces[bucket_index]; node; node= node->next) { 
02655                         project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
02656                 }
02657         }
02658         else {
02659                 
02660                 /* More complicated loop, switch between images */
02661                 for (node = ps->bucketFaces[bucket_index]; node; node= node->next) {
02662                         face_index = GET_INT_FROM_POINTER(node->link);
02663                                 
02664                         /* Image context switching */
02665                         tf = ps->dm_mtface+face_index;
02666                         if (tpage_last != tf->tpage) {
02667                                 tpage_last = tf->tpage;
02668                                 
02669                                 image_index = -1; /* sanity check */
02670                                 
02671                                 for (image_index=0; image_index < ps->image_tot; image_index++) {
02672                                         if (ps->projImages[image_index].ima == tpage_last) {
02673                                                 ibuf = ps->projImages[image_index].ibuf;
02674                                                 ima = ps->projImages[image_index].ima;
02675                                                 break;
02676                                         }
02677                                 }
02678                         }
02679                         /* context switching done */
02680                         
02681                         project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V);
02682                 }
02683         }
02684         
02685         ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT;
02686 }
02687 
02688 
02689 /* We want to know if a bucket and a face overlap in screen-space
02690  * 
02691  * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels
02692  * calculated when it might not be needed later, (at the moment at least)
02693  * obviously it shouldn't have bugs though */
02694 
02695 static int project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf)
02696 {
02697         /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */
02698         rctf bucket_bounds;
02699         float p1[2], p2[2], p3[2], p4[2];
02700         float *v, *v1,*v2,*v3,*v4=NULL;
02701         int fidx;
02702         
02703         project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds);
02704         
02705         /* Is one of the faces verts in the bucket bounds? */
02706         
02707         fidx = mf->v4 ? 3:2;
02708         do {
02709                 v = ps->screenCoords[ (*(&mf->v1 + fidx)) ];
02710                 if (BLI_in_rctf(&bucket_bounds, v[0], v[1])) {
02711                         return 1;
02712                 }
02713         } while (fidx--);
02714         
02715         v1 = ps->screenCoords[mf->v1];
02716         v2 = ps->screenCoords[mf->v2];
02717         v3 = ps->screenCoords[mf->v3];
02718         if (mf->v4) {
02719                 v4 = ps->screenCoords[mf->v4];
02720         }
02721         
02722         p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin;
02723         p2[0] = bucket_bounds.xmin;     p2[1] = bucket_bounds.ymax;
02724         p3[0] = bucket_bounds.xmax;     p3[1] = bucket_bounds.ymax;
02725         p4[0] = bucket_bounds.xmax;     p4[1] = bucket_bounds.ymin;
02726                 
02727         if (mf->v4) {
02728                 if(     isect_point_quad_v2(p1, v1, v2, v3, v4) || isect_point_quad_v2(p2, v1, v2, v3, v4) || isect_point_quad_v2(p3, v1, v2, v3, v4) || isect_point_quad_v2(p4, v1, v2, v3, v4) ||
02729                         /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
02730                         (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3) || isect_line_line_v2(p1, p2, v3, v4)) ||
02731                         (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3) || isect_line_line_v2(p2, p3, v3, v4)) ||
02732                         (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3) || isect_line_line_v2(p3, p4, v3, v4)) ||
02733                         (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3) || isect_line_line_v2(p4, p1, v3, v4))
02734                 ) {
02735                         return 1;
02736                 }
02737         }
02738         else {
02739                 if(     isect_point_tri_v2(p1, v1, v2, v3) || isect_point_tri_v2(p2, v1, v2, v3) || isect_point_tri_v2(p3, v1, v2, v3) || isect_point_tri_v2(p4, v1, v2, v3) ||
02740                         /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */
02741                         (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3)) ||
02742                         (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3)) ||
02743                         (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3)) ||
02744                         (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3))
02745                 ) {
02746                         return 1;
02747                 }
02748         }
02749 
02750         return 0;
02751 }
02752 
02753 /* Add faces to the bucket but dont initialize its pixels
02754  * TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */
02755 static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const int face_index)
02756 {
02757         float min[2], max[2], *vCoSS;
02758         int bucketMin[2], bucketMax[2]; /* for  ps->bucketRect indexing */
02759         int fidx, bucket_x, bucket_y;
02760         int has_x_isect = -1, has_isect = 0; /* for early loop exit */
02761         MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */
02762         
02763         INIT_MINMAX2(min, max);
02764         
02765         fidx = mf->v4 ? 3:2;
02766         do {
02767                 vCoSS = ps->screenCoords[ *(&mf->v1 + fidx) ];
02768                 DO_MINMAX2(vCoSS, min, max);
02769         } while (fidx--);
02770         
02771         project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax);
02772         
02773         for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) {
02774                 has_x_isect = 0;
02775                 for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) {
02776                         if (project_bucket_face_isect(ps, bucket_x, bucket_y, mf)) {
02777                                 int bucket_index= bucket_x + (bucket_y * ps->buckets_x);
02778                                 BLI_linklist_prepend_arena(
02779                                         &ps->bucketFaces[ bucket_index ],
02780                                         SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */
02781                                         arena
02782                                 );
02783                                 
02784                                 has_x_isect = has_isect = 1;
02785                         }
02786                         else if (has_x_isect) {
02787                                 /* assuming the face is not a bow-tie - we know we cant intersect again on the X */
02788                                 break;
02789                         }
02790                 }
02791                 
02792                 /* no intersection for this entire row, after some intersection above means we can quit now */
02793                 if (has_x_isect==0 && has_isect) { 
02794                         break;
02795                 }
02796         }
02797         
02798 #ifndef PROJ_DEBUG_NOSEAMBLEED
02799         if (ps->seam_bleed_px > 0.0f) {
02800                 if (!mf->v4) {
02801                         ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged edge */
02802                 }
02803                 **ps->faceSeamUVs[face_index] = FLT_MAX; /* set as uninitialized */
02804         }
02805 #endif
02806 }
02807 
02808 static int project_paint_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
02809 {
02810         int orth= ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend);
02811 
02812         if (orth) { /* only needed for ortho */
02813                 float fac = 2.0f / ((*clipend) - (*clipsta));
02814                 *clipsta *= fac;
02815                 *clipend *= fac;
02816         }
02817 
02818         return orth;
02819 }
02820 
02821 /* run once per stroke before projection painting */
02822 static void project_paint_begin(ProjPaintState *ps)
02823 {       
02824         /* Viewport vars */
02825         float mat[3][3];
02826         
02827         float no[3];
02828         
02829         float *projScreenCo; /* Note, we could have 4D vectors are only needed for */
02830         float projMargin;
02831 
02832         /* Image Vars - keep track of images we have used */
02833         LinkNode *image_LinkList = NULL;
02834         LinkNode *node;
02835         
02836         ProjPaintImage *projIma;
02837         Image *tpage_last = NULL;
02838         
02839         /* Face vars */
02840         MFace *mf;
02841         MTFace *tf;
02842         
02843         int a, i; /* generic looping vars */
02844         int image_index = -1, face_index;
02845         MVert *mv;
02846         
02847         MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
02848 
02849         const int diameter= 2*brush_size(ps->brush);
02850         
02851         /* ---- end defines ---- */
02852         
02853         if(ps->source==PROJ_SRC_VIEW)
02854                 ED_view3d_local_clipping(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */
02855 
02856         /* paint onto the derived mesh */
02857         
02858         /* Workaround for subsurf selection, try the display mesh first */
02859         if (ps->source==PROJ_SRC_IMAGE_CAM) {
02860                 /* using render mesh, assume only camera was rendered from */
02861                 ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
02862                 ps->dm_release= TRUE;
02863         }
02864         else if(ps->ob->derivedFinal && CustomData_has_layer( &ps->ob->derivedFinal->faceData, CD_MTFACE)) {
02865                 ps->dm = ps->ob->derivedFinal;
02866                 ps->dm_release= FALSE;
02867         }
02868         else {
02869                 ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
02870                 ps->dm_release= TRUE;
02871         }
02872         
02873         if ( !CustomData_has_layer( &ps->dm->faceData, CD_MTFACE) ) {
02874                 
02875                 if(ps->dm_release)
02876                         ps->dm->release(ps->dm);
02877                 
02878                 ps->dm = NULL;
02879                 return; 
02880         }
02881         
02882         ps->dm_mvert = ps->dm->getVertArray(ps->dm);
02883         ps->dm_mface = ps->dm->getFaceArray(ps->dm);
02884         ps->dm_mtface= ps->dm->getFaceDataArray(ps->dm, CD_MTFACE);
02885         
02886         ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
02887         ps->dm_totface = ps->dm->getNumFaces(ps->dm);
02888         
02889         /* use clone mtface? */
02890         
02891         
02892         /* Note, use the original mesh for getting the clone and mask layer index
02893          * this avoids re-generating the derived mesh just to get the new index */
02894         if (ps->do_layer_clone) {
02895                 //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE);
02896                 int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
02897                 if (layer_num != -1)
02898                         ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
02899                 
02900                 if (ps->dm_mtface_clone==NULL || ps->dm_mtface_clone==ps->dm_mtface) {
02901                         ps->do_layer_clone = 0;
02902                         ps->dm_mtface_clone= NULL;
02903                         printf("ACK!\n");
02904                 }
02905         }
02906         
02907         if (ps->do_layer_stencil) {
02908                 //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE);
02909                 int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE);
02910                 if (layer_num != -1)
02911                         ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num);
02912                 
02913                 if (ps->dm_mtface_stencil==NULL || ps->dm_mtface_stencil==ps->dm_mtface) {
02914                         ps->do_layer_stencil = 0;
02915                         ps->dm_mtface_stencil = NULL;
02916                 }
02917         }
02918         
02919         /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
02920         if(ps->dm->type != DM_TYPE_CDDM) {
02921                 ps->dm_mvert= MEM_dupallocN(ps->dm_mvert);
02922                 ps->dm_mface= MEM_dupallocN(ps->dm_mface);
02923                 /* looks like these are ok for now.*/
02924                 /*
02925                 ps->dm_mtface= MEM_dupallocN(ps->dm_mtface);
02926                 ps->dm_mtface_clone= MEM_dupallocN(ps->dm_mtface_clone);
02927                 ps->dm_mtface_stencil= MEM_dupallocN(ps->dm_mtface_stencil);
02928                  */
02929         }
02930         
02931         ps->viewDir[0] = 0.0f;
02932         ps->viewDir[1] = 0.0f;
02933         ps->viewDir[2] = 1.0f;
02934         
02935         {
02936                 float viewmat[4][4];
02937                 float viewinv[4][4];
02938 
02939                 invert_m4_m4(ps->ob->imat, ps->ob->obmat);
02940 
02941                 if(ps->source==PROJ_SRC_VIEW) {
02942                         /* normal drawing */
02943                         ps->winx= ps->ar->winx;
02944                         ps->winy= ps->ar->winy;
02945 
02946                         copy_m4_m4(viewmat, ps->rv3d->viewmat);
02947                         copy_m4_m4(viewinv, ps->rv3d->viewinv);
02948 
02949                         ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat);
02950 
02951                         ps->is_ortho= project_paint_view_clip(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend);
02952                 }
02953                 else {
02954                         /* reprojection */
02955                         float winmat[4][4];
02956                         float vmat[4][4];
02957 
02958                         ps->winx= ps->reproject_ibuf->x;
02959                         ps->winy= ps->reproject_ibuf->y;
02960 
02961                         if (ps->source==PROJ_SRC_IMAGE_VIEW) {
02962                                 /* image stores camera data, tricky */
02963                                 IDProperty *idgroup= IDP_GetProperties(&ps->reproject_image->id, 0);
02964                                 IDProperty *view_data= IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID);
02965 
02966                                 float *array= (float *)IDP_Array(view_data);
02967 
02968                                 /* use image array, written when creating image */
02969                                 memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat)/sizeof(float);
02970                                 memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat)/sizeof(float);
02971                                 ps->clipsta= array[0];
02972                                 ps->clipend= array[1];
02973                                 ps->is_ortho= array[2] ? 1:0;
02974 
02975                                 invert_m4_m4(viewinv, viewmat);
02976                         }
02977                         else if (ps->source==PROJ_SRC_IMAGE_CAM) {
02978                                 Object *camera= ps->scene->camera;
02979 
02980                                 /* dont actually use these */
02981                                 float _viewdx, _viewdy, _ycor, _lens=0.0f;
02982                                 rctf _viewplane;
02983 
02984                                 /* viewmat & viewinv */
02985                                 copy_m4_m4(viewinv, ps->scene->camera->obmat);
02986                                 normalize_m4(viewinv);
02987                                 invert_m4_m4(viewmat, viewinv);
02988 
02989                                 /* camera winmat */
02990                                 object_camera_mode(&ps->scene->r, camera);
02991                                 object_camera_matrix(&ps->scene->r, camera, ps->winx, ps->winy, 0,
02992                                                 winmat, &_viewplane, &ps->clipsta, &ps->clipend,
02993                                                 &_lens, &_ycor, &_viewdx, &_viewdy);
02994 
02995                                 ps->is_ortho= (ps->scene->r.mode & R_ORTHO) ? 1 : 0;
02996                         }
02997 
02998                         /* same as view3d_get_object_project_mat */
02999                         mul_m4_m4m4(vmat, ps->ob->obmat, viewmat);
03000                         mul_m4_m4m4(ps->projectMat, vmat, winmat);
03001                 }
03002 
03003 
03004                 /* viewDir - object relative */
03005                 invert_m4_m4(ps->ob->imat, ps->ob->obmat);
03006                 copy_m3_m4(mat, viewinv);
03007                 mul_m3_v3(mat, ps->viewDir);
03008                 copy_m3_m4(mat, ps->ob->imat);
03009                 mul_m3_v3(mat, ps->viewDir);
03010                 normalize_v3(ps->viewDir);
03011                 
03012                 /* viewPos - object relative */
03013                 VECCOPY(ps->viewPos, viewinv[3]);
03014                 copy_m3_m4(mat, ps->ob->imat);
03015                 mul_m3_v3(mat, ps->viewPos);
03016                 add_v3_v3(ps->viewPos, ps->ob->imat[3]);
03017         }
03018         
03019         /* calculate vert screen coords
03020          * run this early so we can calculate the x/y resolution of our bucket rect */
03021         INIT_MINMAX2(ps->screenMin, ps->screenMax);
03022         
03023         ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
03024         projScreenCo= *ps->screenCoords;
03025         
03026         if (ps->is_ortho) {
03027                 for(a=0, mv=ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo+=4) {
03028                         mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
03029                         
03030                         /* screen space, not clamped */
03031                         projScreenCo[0] = (float)(ps->winx/2.0f)+(ps->winx/2.0f)*projScreenCo[0];
03032                         projScreenCo[1] = (float)(ps->winy/2.0f)+(ps->winy/2.0f)*projScreenCo[1];
03033                         DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax);
03034                 }
03035         }
03036         else {
03037                 for(a=0, mv=ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo+=4) {
03038                         copy_v3_v3(projScreenCo, mv->co);
03039                         projScreenCo[3] = 1.0f;
03040 
03041                         mul_m4_v4(ps->projectMat, projScreenCo);
03042 
03043                         if (projScreenCo[3] > ps->clipsta) {
03044                                 /* screen space, not clamped */
03045                                 projScreenCo[0] = (float)(ps->winx/2.0f)+(ps->winx/2.0f)*projScreenCo[0]/projScreenCo[3];
03046                                 projScreenCo[1] = (float)(ps->winy/2.0f)+(ps->winy/2.0f)*projScreenCo[1]/projScreenCo[3];
03047                                 projScreenCo[2] = projScreenCo[2]/projScreenCo[3]; /* Use the depth for bucket point occlusion */
03048                                 DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax);
03049                         }
03050                         else {
03051                                 /* TODO - deal with cases where 1 side of a face goes behind the view ?
03052                                  * 
03053                                  * After some research this is actually very tricky, only option is to
03054                                  * clip the derived mesh before painting, which is a Pain */
03055                                 projScreenCo[0] = FLT_MAX;
03056                         }
03057                 }
03058         }
03059         
03060         /* If this border is not added we get artifacts for faces that
03061          * have a parallel edge and at the bounds of the the 2D projected verts eg
03062          * - a single screen aligned quad */
03063         projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f;
03064         ps->screenMax[0] += projMargin;
03065         ps->screenMin[0] -= projMargin;
03066         projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f;
03067         ps->screenMax[1] += projMargin;
03068         ps->screenMin[1] -= projMargin;
03069         
03070         if(ps->source==PROJ_SRC_VIEW) {
03071 #ifdef PROJ_DEBUG_WINCLIP
03072                 CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter));
03073                 CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter));
03074 
03075                 CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter));
03076                 CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter));
03077 #endif
03078         }
03079         else { /* reprojection, use bounds */
03080                 ps->screenMin[0]= 0;
03081                 ps->screenMax[0]= (float)(ps->winx);
03082 
03083                 ps->screenMin[1]= 0;
03084                 ps->screenMax[1]= (float)(ps->winy);
03085         }
03086 
03087         /* only for convenience */
03088         ps->screen_width  = ps->screenMax[0] - ps->screenMin[0];
03089         ps->screen_height = ps->screenMax[1] - ps->screenMin[1];
03090         
03091         ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
03092         ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV));
03093         
03094         /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
03095         
03096         /* really high values could cause problems since it has to allocate a few
03097          * (ps->buckets_x*ps->buckets_y) sized arrays  */
03098         CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
03099         CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
03100         
03101         ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect");
03102         ps->bucketFaces= (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
03103         
03104         ps->bucketFlags= (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces");
03105 #ifndef PROJ_DEBUG_NOSEAMBLEED
03106         if (ps->seam_bleed_px > 0.0f) {
03107                 ps->vertFaces= (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
03108                 ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags");
03109                 ps->faceSeamUVs= MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs");
03110         }
03111 #endif
03112         
03113         /* Thread stuff
03114          * 
03115          * very small brushes run a lot slower multithreaded since the advantage with
03116          * threads is being able to fill in multiple buckets at once.
03117          * Only use threads for bigger brushes. */
03118         
03119         if (ps->scene->r.mode & R_FIXED_THREADS) {
03120                 ps->thread_tot = ps->scene->r.threads;
03121         }
03122         else {
03123                 ps->thread_tot = BLI_system_thread_count();
03124         }
03125         for (a=0; a<ps->thread_tot; a++) {
03126                 ps->arena_mt[a] = BLI_memarena_new(1<<16, "project paint arena");
03127         }
03128         
03129         arena = ps->arena_mt[0]; 
03130         
03131         if (ps->do_backfacecull && ps->do_mask_normal) {
03132                 float viewDirPersp[3];
03133                 
03134                 ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
03135                 
03136                 for(a=0, mv=ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
03137                         normal_short_to_float_v3(no, mv->no);
03138                         
03139                         if (ps->is_ortho) {
03140                                 if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
03141                                         ps->vertFlags[a] |= PROJ_VERT_CULL;
03142                                 }
03143                         }
03144                         else {
03145                                 sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co);
03146                                 normalize_v3(viewDirPersp);
03147                                 if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */
03148                                         ps->vertFlags[a] |= PROJ_VERT_CULL;
03149                                 }
03150                         }
03151                 }
03152         }
03153         
03154 
03155         for(face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) {
03156                 
03157 #ifndef PROJ_DEBUG_NOSEAMBLEED
03158                 /* add face user if we have bleed enabled, set the UV seam flags later */
03159                 /* annoying but we need to add all faces even ones we never use elsewhere */
03160                 if (ps->seam_bleed_px > 0.0f) {
03161                         BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena);
03162                         BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena);
03163                         BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena);
03164                         if (mf->v4) {
03165                                 BLI_linklist_prepend_arena(&ps->vertFaces[mf->v4], SET_INT_IN_POINTER(face_index), arena);
03166                         }
03167                 }
03168 #endif
03169                 
03170                 if (tf->tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_MASK)==0 || mf->flag & ME_FACE_SEL)) {
03171                         
03172                         float *v1coSS, *v2coSS, *v3coSS, *v4coSS=NULL;
03173                         
03174                         v1coSS = ps->screenCoords[mf->v1]; 
03175                         v2coSS = ps->screenCoords[mf->v2]; 
03176                         v3coSS = ps->screenCoords[mf->v3];
03177                         if (mf->v4) {
03178                                 v4coSS = ps->screenCoords[mf->v4]; 
03179                         }
03180                         
03181                         
03182                         if (!ps->is_ortho) {
03183                                 if (    v1coSS[0]==FLT_MAX ||
03184                                                 v2coSS[0]==FLT_MAX ||
03185                                                 v3coSS[0]==FLT_MAX ||
03186                                                 (mf->v4 && v4coSS[0]==FLT_MAX)
03187                                 ) {
03188                                         continue;
03189                                 }
03190                         }
03191                         
03192 #ifdef PROJ_DEBUG_WINCLIP
03193                         /* ignore faces outside the view */
03194                         if (
03195                                    (v1coSS[0] < ps->screenMin[0] &&
03196                                         v2coSS[0] < ps->screenMin[0] &&
03197                                         v3coSS[0] < ps->screenMin[0] &&
03198                                         (mf->v4 && v4coSS[0] < ps->screenMin[0])) ||
03199                                         
03200                                    (v1coSS[0] > ps->screenMax[0] &&
03201                                         v2coSS[0] > ps->screenMax[0] &&
03202                                         v3coSS[0] > ps->screenMax[0] &&
03203                                         (mf->v4 && v4coSS[0] > ps->screenMax[0])) ||
03204                                         
03205                                    (v1coSS[1] < ps->screenMin[1] &&
03206                                         v2coSS[1] < ps->screenMin[1] &&
03207                                         v3coSS[1] < ps->screenMin[1] &&
03208                                         (mf->v4 && v4coSS[1] < ps->screenMin[1])) ||
03209                                         
03210                                    (v1coSS[1] > ps->screenMax[1] &&
03211                                         v2coSS[1] > ps->screenMax[1] &&
03212                                         v3coSS[1] > ps->screenMax[1] &&
03213                                         (mf->v4 && v4coSS[1] > ps->screenMax[1]))
03214                         ) {
03215                                 continue;
03216                         }
03217                         
03218 #endif //PROJ_DEBUG_WINCLIP
03219         
03220                         
03221                         if (ps->do_backfacecull) {
03222                                 if (ps->do_mask_normal) {
03223                                         /* Since we are interpolating the normals of faces, we want to make 
03224                                          * sure all the verts are pointing away from the view,
03225                                          * not just the face */
03226                                         if (    (ps->vertFlags[mf->v1] & PROJ_VERT_CULL) &&
03227                                                         (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) &&
03228                                                         (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) &&
03229                                                         (mf->v4==0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL)
03230                                                         
03231                                         ) {
03232                                                 continue;
03233                                         }
03234                                 }
03235                                 else {
03236                                         if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) {
03237                                                 continue;
03238                                         }
03239                                         
03240                                 }
03241                         }
03242                         
03243                         if (tpage_last != tf->tpage) {
03244                                 
03245                                 image_index = BLI_linklist_index(image_LinkList, tf->tpage);
03246                                 
03247                                 if (image_index==-1 && BKE_image_get_ibuf(tf->tpage, NULL)) { /* MemArena dosnt have an append func */
03248                                         BLI_linklist_append(&image_LinkList, tf->tpage);
03249                                         image_index = ps->image_tot;
03250                                         ps->image_tot++;
03251                                 }
03252                                 
03253                                 tpage_last = tf->tpage;
03254                         }
03255                         
03256                         if (image_index != -1) {
03257                                 /* Initialize the faces screen pixels */
03258                                 /* Add this to a list to initialize later */
03259                                 project_paint_delayed_face_init(ps, mf, face_index);
03260                         }
03261                 }
03262         }
03263         
03264         /* build an array of images we use*/
03265         projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
03266         
03267         for (node= image_LinkList, i=0; node; node= node->next, i++, projIma++) {
03268                 projIma->ima = node->link;
03269                 projIma->touch = 0;
03270                 projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL);
03271                 projIma->partRedrawRect =  BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
03272                 memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
03273         }
03274         
03275         /* we have built the array, discard the linked list */
03276         BLI_linklist_free(image_LinkList, NULL);
03277 }
03278 
03279 static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2])
03280 {
03281         /* setup clone offset */
03282         if (ps->tool == PAINT_TOOL_CLONE) {
03283                 float projCo[4];
03284                 copy_v3_v3(projCo, give_cursor(ps->scene, ps->v3d));
03285                 mul_m4_v3(ps->ob->imat, projCo);
03286                 
03287                 projCo[3] = 1.0f;
03288                 mul_m4_v4(ps->projectMat, projCo);
03289                 ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx/2.0f)+(ps->winx/2.0f)*projCo[0]/projCo[3]);
03290                 ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy/2.0f)+(ps->winy/2.0f)*projCo[1]/projCo[3]);
03291         }       
03292 }       
03293 
03294 static void project_paint_end(ProjPaintState *ps)
03295 {
03296         int a;
03297         
03298         /* build undo data from original pixel colors */
03299         if(U.uiflag & USER_GLOBALUNDO) {
03300                 ProjPixel *projPixel;
03301                 ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL;
03302                 LinkNode *pixel_node;
03303                 void *tilerect;
03304                 MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */
03305                                 
03306                 int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */
03307                 int bucket_index; 
03308                 int tile_index;
03309                 int x_round, y_round;
03310                 int x_tile, y_tile;
03311                 int is_float = -1;
03312                 
03313                 /* context */
03314                 ProjPaintImage *last_projIma;
03315                 int last_image_index = -1;
03316                 int last_tile_width=0;
03317                 
03318                 for(a=0, last_projIma=ps->projImages; a < ps->image_tot; a++, last_projIma++) {
03319                         int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y);
03320                         last_projIma->undoRect = (void **) BLI_memarena_alloc(arena, size);
03321                         memset(last_projIma->undoRect, 0, size);
03322                         last_projIma->ibuf->userflags |= IB_BITMAPDIRTY;
03323                 }
03324                 
03325                 for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) {
03326                         /* loop through all pixels */
03327                         for(pixel_node= ps->bucketRect[bucket_index]; pixel_node; pixel_node= pixel_node->next) {
03328                         
03329                                 /* ok we have a pixel, was it modified? */
03330                                 projPixel = (ProjPixel *)pixel_node->link;
03331                                 
03332                                 if (last_image_index != projPixel->image_index) {
03333                                         /* set the context */
03334                                         last_image_index =      projPixel->image_index;
03335                                         last_projIma =          ps->projImages + last_image_index;
03336                                         last_tile_width =       IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x);
03337                                         is_float =                      last_projIma->ibuf->rect_float ? 1 : 0;
03338                                 }
03339                                 
03340                                 
03341                                 if (    (is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) || 
03342                                                                 
03343                                                 (is_float == 1 && 
03344                                                 (       projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] || 
03345                                                         projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] ||
03346                                                         projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] ||
03347                                                         projPixel->origColor.f[3] != projPixel->pixel.f_pt[3] ))
03348                                 ) {
03349                                         
03350                                         x_tile =  projPixel->x_px >> IMAPAINT_TILE_BITS;
03351                                         y_tile =  projPixel->y_px >> IMAPAINT_TILE_BITS;
03352                                         
03353                                         x_round = x_tile * IMAPAINT_TILE_SIZE;
03354                                         y_round = y_tile * IMAPAINT_TILE_SIZE;
03355                                         
03356                                         tile_index = x_tile + y_tile * last_tile_width;
03357                                         
03358                                         if (last_projIma->undoRect[tile_index]==NULL) {
03359                                                 /* add the undo tile from the modified image, then write the original colors back into it */
03360                                                 tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float):(&tmpibuf) , x_tile, y_tile);
03361                                         }
03362                                         else {
03363                                                 tilerect = last_projIma->undoRect[tile_index];
03364                                         }
03365                                         
03366                                         /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color
03367                                          * because allocating the tiles allong the way slows down painting */
03368                                         
03369                                         if (is_float) {
03370                                                 float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4;
03371                                                 QUATCOPY(rgba_fp, projPixel->origColor.f);
03372                                         }
03373                                         else {
03374                                                 ((unsigned int *)tilerect)[ (projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE ] = projPixel->origColor.uint;
03375                                         }
03376                                 }
03377                         }
03378                 }
03379                 
03380                 if (tmpibuf)            IMB_freeImBuf(tmpibuf);
03381                 if (tmpibuf_float)      IMB_freeImBuf(tmpibuf_float);
03382         }
03383         /* done calculating undo data */
03384         
03385         MEM_freeN(ps->screenCoords);
03386         MEM_freeN(ps->bucketRect);
03387         MEM_freeN(ps->bucketFaces);
03388         MEM_freeN(ps->bucketFlags);
03389         
03390 #ifndef PROJ_DEBUG_NOSEAMBLEED
03391         if (ps->seam_bleed_px > 0.0f) {
03392                 MEM_freeN(ps->vertFaces);
03393                 MEM_freeN(ps->faceSeamFlags);
03394                 MEM_freeN(ps->faceSeamUVs);
03395         }
03396 #endif
03397         
03398         if (ps->vertFlags) MEM_freeN(ps->vertFlags);
03399         
03400         for (a=0; a<ps->thread_tot; a++) {
03401                 BLI_memarena_free(ps->arena_mt[a]);
03402         }
03403         
03404         /* copy for subsurf/multires, so throw away */
03405         if(ps->dm->type != DM_TYPE_CDDM) {
03406                 if(ps->dm_mvert) MEM_freeN(ps->dm_mvert);
03407                 if(ps->dm_mface) MEM_freeN(ps->dm_mface);
03408                 /* looks like these dont need copying */
03409                 /*
03410                 if(ps->dm_mtface) MEM_freeN(ps->dm_mtface);
03411                 if(ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone);
03412                 if(ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil);
03413                 */
03414         }
03415 
03416         if(ps->dm_release)
03417                 ps->dm->release(ps->dm);
03418 }
03419 
03420 /* 1= an undo, -1 is a redo. */
03421 static void partial_redraw_array_init(ImagePaintPartialRedraw *pr)
03422 {
03423         int tot = PROJ_BOUNDBOX_SQUARED;
03424         while (tot--) {
03425                 pr->x1 = 10000000;
03426                 pr->y1 = 10000000;
03427                 
03428                 pr->x2 = -1;
03429                 pr->y2 = -1;
03430                 
03431                 pr->enabled = 1;
03432                 
03433                 pr++;
03434         }
03435 }
03436 
03437 
03438 static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot)
03439 {
03440         int touch= 0;
03441         while (tot--) {
03442                 pr->x1 = MIN2(pr->x1, pr_other->x1);
03443                 pr->y1 = MIN2(pr->y1, pr_other->y1);
03444                 
03445                 pr->x2 = MAX2(pr->x2, pr_other->x2);
03446                 pr->y2 = MAX2(pr->y2, pr_other->y2);
03447                 
03448                 if (pr->x2 != -1)
03449                         touch = 1;
03450                 
03451                 pr++; pr_other++;
03452         }
03453         
03454         return touch;
03455 }
03456 
03457 /* Loop over all images on this mesh and update any we have touched */
03458 static int project_image_refresh_tagged(ProjPaintState *ps)
03459 {
03460         ImagePaintPartialRedraw *pr;
03461         ProjPaintImage *projIma;
03462         int a,i;
03463         int redraw = 0;
03464         
03465         
03466         for (a=0, projIma=ps->projImages; a < ps->image_tot; a++, projIma++) {
03467                 if (projIma->touch) {
03468                         /* look over each bound cell */
03469                         for (i=0; i<PROJ_BOUNDBOX_SQUARED; i++) {
03470                                 pr = &(projIma->partRedrawRect[i]);
03471                                 if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
03472                                         imapaintpartial = *pr;
03473                                         imapaint_image_update(NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/
03474                                         redraw = 1;
03475                                 }
03476                         }
03477                         
03478                         projIma->touch = 0; /* clear for reuse */
03479                 }
03480         }
03481         
03482         return redraw;
03483 }
03484 
03485 /* run this per painting onto each mouse location */
03486 static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2])
03487 {
03488         if(ps->source==PROJ_SRC_VIEW) {
03489                 float min_brush[2], max_brush[2];
03490                 const float radius = (float)brush_size(ps->brush);
03491 
03492                 /* so we dont have a bucket bounds that is way too small to paint into */
03493                 // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/
03494 
03495                 min_brush[0] = mval_f[0] - radius;
03496                 min_brush[1] = mval_f[1] - radius;
03497 
03498                 max_brush[0] = mval_f[0] + radius;
03499                 max_brush[1] = mval_f[1] + radius;
03500 
03501                 /* offset to make this a valid bucket index */
03502                 project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax);
03503 
03504                 /* mouse outside the model areas? */
03505                 if (ps->bucketMin[0]==ps->bucketMax[0] || ps->bucketMin[1]==ps->bucketMax[1]) {
03506                         return 0;
03507                 }
03508 
03509                 ps->context_bucket_x = ps->bucketMin[0];
03510                 ps->context_bucket_y = ps->bucketMin[1];
03511         }
03512         else { /* reproject: PROJ_SRC_* */
03513                 ps->bucketMin[0]= 0;
03514                 ps->bucketMin[1]= 0;
03515 
03516                 ps->bucketMax[0]= ps->buckets_x;
03517                 ps->bucketMax[1]= ps->buckets_y;
03518 
03519                 ps->context_bucket_x = 0;
03520                 ps->context_bucket_y = 0;
03521         }
03522         return 1;
03523 }
03524 
03525 
03526 static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2])
03527 {
03528         const int diameter= 2*brush_size(ps->brush);
03529 
03530         if (ps->thread_tot > 1)
03531                 BLI_lock_thread(LOCK_CUSTOM1);
03532         
03533         //printf("%d %d \n", ps->context_bucket_x, ps->context_bucket_y);
03534         
03535         for ( ; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) {
03536                 for ( ; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) {
03537                         
03538                         /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/
03539                         project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds);
03540                         
03541                         if (    (ps->source != PROJ_SRC_VIEW) ||
03542                                         project_bucket_isect_circle(mval, (float)(diameter*diameter), bucket_bounds)
03543                         ) {
03544                                 *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x);
03545                                 ps->context_bucket_x++;
03546                                 
03547                                 if (ps->thread_tot > 1)
03548                                         BLI_unlock_thread(LOCK_CUSTOM1);
03549                                 
03550                                 return 1;
03551                         }
03552                 }
03553                 ps->context_bucket_x = ps->bucketMin[0];
03554         }
03555         
03556         if (ps->thread_tot > 1)
03557                 BLI_unlock_thread(LOCK_CUSTOM1);
03558         return 0;
03559 }
03560 
03561 /* Each thread gets one of these, also used as an argument to pass to project_paint_op */
03562 typedef struct ProjectHandle {
03563         /* args */
03564         ProjPaintState *ps;
03565         float prevmval[2];
03566         float mval[2];
03567         
03568         /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */
03569         ProjPaintImage *projImages;     /* array of partial redraws */
03570         
03571         /* thread settings */
03572         int thread_index;
03573 } ProjectHandle;
03574 
03575 static void blend_color_mix(unsigned char *cp, const unsigned char *cp1, const unsigned char *cp2, const int fac)
03576 {
03577         /* this and other blending modes previously used >>8 instead of /255. both
03578            are not equivalent (>>8 is /256), and the former results in rounding
03579            errors that can turn colors black fast after repeated blending */
03580         const int mfac= 255-fac;
03581 
03582         cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
03583         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
03584         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
03585         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
03586 }
03587 
03588 static void blend_color_mix_float(float *cp, const float *cp1, const float *cp2, const float fac)
03589 {
03590         const float mfac= 1.0f-fac;
03591         cp[0]= mfac*cp1[0] + fac*cp2[0];
03592         cp[1]= mfac*cp1[1] + fac*cp2[1];
03593         cp[2]= mfac*cp1[2] + fac*cp2[2];
03594         cp[3]= mfac*cp1[3] + fac*cp2[3];
03595 }
03596 
03597 static void blend_color_mix_accum(unsigned char *cp, const unsigned char *cp1, const unsigned char *cp2, const int fac)
03598 {
03599         /* this and other blending modes previously used >>8 instead of /255. both
03600            are not equivalent (>>8 is /256), and the former results in rounding
03601            errors that can turn colors black fast after repeated blending */
03602         const int mfac= 255-fac;
03603         const int alpha= cp1[3] + ((fac * cp2[3]) / 255);
03604 
03605         cp[0]= (mfac*cp1[0]+fac*cp2[0])/255;
03606         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
03607         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
03608         cp[3]= alpha > 255 ? 255 : alpha;
03609 }
03610 
03611 static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
03612 {
03613         if (ps->is_airbrush==0 && mask < 1.0f) {
03614                 projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*255), ps->blend);
03615                 blend_color_mix(projPixel->pixel.ch_pt,  projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255));
03616         }
03617         else {
03618                 *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone*)projPixel)->clonepx.uint, (int)(alpha*mask*255), ps->blend);
03619         }
03620 }
03621 
03622 static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask)
03623 {
03624         if (ps->is_airbrush==0 && mask < 1.0f) {
03625                 IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend);
03626                 blend_color_mix_float(projPixel->pixel.f_pt,  projPixel->origColor.f, projPixel->newColor.f, mask);
03627         }
03628         else {
03629                 IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha*mask, ps->blend);
03630         }
03631 }
03632 
03633 /* do_projectpaint_smear*
03634  * 
03635  * note, mask is used to modify the alpha here, this is not correct since it allows
03636  * accumulation of color greater then 'projPixel->mask' however in the case of smear its not 
03637  * really that important to be correct as it is with clone and painting 
03638  */
03639 static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2])
03640 {
03641         unsigned char rgba_ub[4];
03642         
03643         if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
03644                 return; 
03645         /* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
03646         blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha*mask*255));
03647         BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena);
03648 } 
03649 
03650 static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2])
03651 {
03652         unsigned char rgba_ub[4];
03653         unsigned char rgba_smear[4];
03654         
03655         if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1)==0)
03656                 return;
03657         
03658         IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_smear, projPixel->pixel.f_pt);
03659         /* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */
03660         blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, rgba_smear, (rgba_ub), (int)(alpha*mask*255)); 
03661         BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena);
03662 }
03663 
03664 static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask)
03665 {
03666         unsigned char rgba_ub[4];
03667         
03668         if (ps->is_texbrush) {
03669                 rgba_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]);
03670                 rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]);
03671                 rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]);
03672                 rgba_ub[3] = FTOCHAR(rgba[3]);
03673         }
03674         else {
03675                 IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb);
03676                 rgba_ub[3] = 255;
03677         }
03678         
03679         if (ps->is_airbrush==0 && mask < 1.0f) {
03680                 projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha*255), ps->blend);
03681                 blend_color_mix(projPixel->pixel.ch_pt,  projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*255));
03682         }
03683         else {
03684                 *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend);
03685         }
03686 }
03687 
03688 static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, int use_color_correction) {
03689         if (ps->is_texbrush) {
03690                 /* rgba already holds a texture result here from higher level function */
03691                 float rgba_br[3];
03692                 if(use_color_correction){
03693                         srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb);
03694                         mul_v3_v3(rgba, rgba_br);
03695                 }
03696                 else{
03697                         mul_v3_v3(rgba, ps->brush->rgb);
03698                 }
03699         }
03700         else {
03701                 if(use_color_correction){
03702                         srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb);
03703                 }
03704                 else {
03705                         VECCOPY(rgba, ps->brush->rgb);
03706                 }
03707                 rgba[3] = 1.0;
03708         }
03709         
03710         if (ps->is_airbrush==0 && mask < 1.0f) {
03711                 IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend);
03712                 blend_color_mix_float(projPixel->pixel.f_pt,  projPixel->origColor.f, projPixel->newColor.f, mask);
03713         }
03714         else {
03715                 IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha*mask, ps->blend);
03716         }
03717 }
03718 
03719 
03720 
03721 /* run this for single and multithreaded painting */
03722 static void *do_projectpaint_thread(void *ph_v)
03723 {
03724         /* First unpack args from the struct */
03725         ProjPaintState *ps =                    ((ProjectHandle *)ph_v)->ps;
03726         ProjPaintImage *projImages =    ((ProjectHandle *)ph_v)->projImages;
03727         const float *lastpos =                  ((ProjectHandle *)ph_v)->prevmval;
03728         const float *pos =                              ((ProjectHandle *)ph_v)->mval;
03729         const int thread_index =                ((ProjectHandle *)ph_v)->thread_index;
03730         /* Done with args from ProjectHandle */
03731 
03732         LinkNode *node;
03733         ProjPixel *projPixel;
03734         
03735         int last_index = -1;
03736         ProjPaintImage *last_projIma= NULL;
03737         ImagePaintPartialRedraw *last_partial_redraw_cell;
03738         
03739         float rgba[4], alpha, dist_nosqrt, dist;
03740         
03741         float falloff;
03742         int bucket_index;
03743         int is_floatbuf = 0;
03744         int use_color_correction = 0;
03745         const short tool =  ps->tool;
03746         rctf bucket_bounds;
03747         
03748         /* for smear only */
03749         float pos_ofs[2] = {0};
03750         float co[2];
03751         float mask = 1.0f; /* airbrush wont use mask */
03752         unsigned short mask_short;
03753         const float radius= (float)brush_size(ps->brush);
03754         const float radius_squared= radius*radius; /* avoid a square root with every dist comparison */
03755         
03756         short lock_alpha= ELEM(ps->brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : ps->brush->flag & BRUSH_LOCK_ALPHA;
03757         
03758         LinkNode *smearPixels = NULL;
03759         LinkNode *smearPixels_f = NULL;
03760         MemArena *smearArena = NULL; /* mem arena for this brush projection only */
03761         
03762         if (tool==PAINT_TOOL_SMEAR) {
03763                 pos_ofs[0] = pos[0] - lastpos[0];
03764                 pos_ofs[1] = pos[1] - lastpos[1];
03765                 
03766                 smearArena = BLI_memarena_new(1<<16, "paint smear arena");
03767         }
03768         
03769         /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */
03770         
03771         while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) {                              
03772                 
03773                 /* Check this bucket and its faces are initialized */
03774                 if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) {
03775                         /* No pixels initialized */
03776                         project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds);
03777                 }
03778 
03779                 if(ps->source != PROJ_SRC_VIEW) {
03780 
03781                         /* Re-Projection, simple, no brushes! */
03782                         
03783                         for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
03784                                 projPixel = (ProjPixel *)node->link;
03785 
03786                                 bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, projPixel->projCoSS[0], projPixel->projCoSS[1]);
03787                                 if(projPixel->newColor.ch[3]) {
03788                                         mask = ((float)projPixel->mask)/65535.0f;
03789                                         blend_color_mix_accum(projPixel->pixel.ch_pt,  projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask*projPixel->newColor.ch[3]));
03790 
03791                                 }
03792                         }
03793                 }
03794                 else {
03795                         /* Normal brush painting */
03796                         
03797                         for (node = ps->bucketRect[bucket_index]; node; node = node->next) {
03798 
03799                                 projPixel = (ProjPixel *)node->link;
03800 
03801                                 /*dist = len_v2v2(projPixel->projCoSS, pos);*/ /* correct but uses a sqrtf */
03802                                 dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos);
03803 
03804                                 /*if (dist < radius) {*/ /* correct but uses a sqrtf */
03805                                 if (dist_nosqrt <= radius_squared) {
03806                                         dist=sqrtf(dist_nosqrt);
03807 
03808                                         falloff = brush_curve_strength_clamp(ps->brush, dist, radius);
03809 
03810                                         if (falloff > 0.0f) {
03811                                                 if (ps->is_texbrush) {
03812                                                         /* note, for clone and smear, we only use the alpha, could be a special function */
03813                                                         brush_sample_tex(ps->brush, projPixel->projCoSS, rgba, thread_index);
03814                                                         alpha = rgba[3];
03815                                                 } else {
03816                                                         alpha = 1.0f;
03817                                                 }
03818                                                 
03819                                                 if (ps->is_airbrush) {
03820                                                         /* for an aurbrush there is no real mask, so just multiply the alpha by it */
03821                                                         alpha *= falloff * brush_alpha(ps->brush);
03822                                                         mask = ((float)projPixel->mask)/65535.0f;
03823                                                 }
03824                                                 else {
03825                                                         /* This brush dosnt accumulate so add some curve to the brushes falloff */
03826                                                         falloff = 1.0f - falloff;
03827                                                         falloff = 1.0f - (falloff * falloff);
03828                                                         
03829                                                         mask_short = (unsigned short)(projPixel->mask * (brush_alpha(ps->brush) * falloff));
03830                                                         if (mask_short > projPixel->mask_max) {
03831                                                                 mask = ((float)mask_short)/65535.0f;
03832                                                                 projPixel->mask_max = mask_short;
03833                                                         }
03834                                                         else {
03835                                                                 /*mask = ((float)projPixel->mask_max)/65535.0f;*/
03836 
03837                                                                 /* Go onto the next pixel */
03838                                                                 continue;
03839                                                         }
03840                                                 }
03841                                                 
03842                                                 if (alpha > 0.0f) {
03843 
03844                                                         if (last_index != projPixel->image_index) {
03845                                                                 last_index = projPixel->image_index;
03846                                                                 last_projIma = projImages + last_index;
03847 
03848                                                                 last_projIma->touch = 1;
03849                                                                 is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
03850                                                                 use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0;
03851                                                         }
03852 
03853                                                         last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index;
03854                                                         last_partial_redraw_cell->x1 = MIN2(last_partial_redraw_cell->x1, projPixel->x_px);
03855                                                         last_partial_redraw_cell->y1 = MIN2(last_partial_redraw_cell->y1, projPixel->y_px);
03856 
03857                                                         last_partial_redraw_cell->x2 = MAX2(last_partial_redraw_cell->x2, projPixel->x_px+1);
03858                                                         last_partial_redraw_cell->y2 = MAX2(last_partial_redraw_cell->y2, projPixel->y_px+1);
03859 
03860                                                         
03861                                                         switch(tool) {
03862                                                         case PAINT_TOOL_CLONE:
03863                                                                 if (is_floatbuf) {
03864                                                                         if (((ProjPixelClone *)projPixel)->clonepx.f[3]) {
03865                                                                                 do_projectpaint_clone_f(ps, projPixel, alpha, mask); /* rgba isnt used for cloning, only alpha */
03866                                                                         }
03867                                                                 }
03868                                                                 else {
03869                                                                         if (((ProjPixelClone*)projPixel)->clonepx.ch[3]) {
03870                                                                                 do_projectpaint_clone(ps, projPixel, alpha, mask); /* rgba isnt used for cloning, only alpha */
03871                                                                         }
03872                                                                 }
03873                                                                 break;
03874                                                         case PAINT_TOOL_SMEAR:
03875                                                                 sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs);
03876 
03877                                                                 if (is_floatbuf)        do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co);
03878                                                                 else                            do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co);
03879                                                                 break;
03880                                                         default:
03881                                                                 if (is_floatbuf)        do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask, use_color_correction);
03882                                                                 else                            do_projectpaint_draw(ps, projPixel, rgba, alpha, mask);
03883                                                                 break;
03884                                                         }
03885                                                 }
03886 
03887                                                 if(lock_alpha) {
03888                                                         if (is_floatbuf)        projPixel->pixel.f_pt[3]= projPixel->origColor.f[3];
03889                                                         else                            projPixel->pixel.ch_pt[3]= projPixel->origColor.ch[3];
03890                                                 }
03891 
03892                                                 /* done painting */
03893                                         }
03894                                 }
03895                         }
03896                 }
03897         }
03898 
03899         
03900         if (tool==PAINT_TOOL_SMEAR) {
03901                 
03902                 for (node= smearPixels; node; node= node->next) { /* this wont run for a float image */
03903                         projPixel = node->link;
03904                         *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint;
03905                 }
03906                 
03907                 for (node= smearPixels_f; node; node= node->next) {
03908                         projPixel = node->link;
03909                         IMAPAINT_CHAR_RGBA_TO_FLOAT(projPixel->pixel.f_pt,  ((ProjPixelClone *)projPixel)->clonepx.ch);
03910                 }
03911                 
03912                 BLI_memarena_free(smearArena);
03913         }
03914         
03915         return NULL;
03916 }
03917 
03918 static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), float *lastpos, float *pos)
03919 {
03920         /* First unpack args from the struct */
03921         ProjPaintState *ps = (ProjPaintState *)state;
03922         int touch_any = 0;      
03923         
03924         ProjectHandle handles[BLENDER_MAX_THREADS];
03925         ListBase threads;
03926         int a,i;
03927         
03928         if (!project_bucket_iter_init(ps, pos)) {
03929                 return 0;
03930         }
03931         
03932         if (ps->thread_tot > 1)
03933                 BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot);
03934         
03935         /* get the threads running */
03936         for(a=0; a < ps->thread_tot; a++) {
03937                 
03938                 /* set defaults in handles */
03939                 //memset(&handles[a], 0, sizeof(BakeShade));
03940                 
03941                 handles[a].ps = ps;
03942                 copy_v2_v2(handles[a].mval, pos);
03943                 copy_v2_v2(handles[a].prevmval, lastpos);
03944                 
03945                 /* thread spesific */
03946                 handles[a].thread_index = a;
03947                 
03948                 handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage));
03949                 
03950                 memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage));
03951                 
03952                 /* image bounds */
03953                 for (i=0; i< ps->image_tot; i++) {
03954                         handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
03955                         memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);                     
03956                 }
03957 
03958                 if (ps->thread_tot > 1)
03959                         BLI_insert_thread(&threads, &handles[a]);
03960         }
03961         
03962         if (ps->thread_tot > 1) /* wait for everything to be done */
03963                 BLI_end_threads(&threads);
03964         else
03965                 do_projectpaint_thread(&handles[0]);
03966                 
03967         
03968         /* move threaded bounds back into ps->projectPartialRedraws */
03969         for(i=0; i < ps->image_tot; i++) {
03970                 int touch = 0;
03971                 for(a=0; a < ps->thread_tot; a++) {
03972                         touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED);
03973                 }
03974                 
03975                 if (touch) {
03976                         ps->projImages[i].touch = 1;
03977                         touch_any = 1;
03978                 }
03979         }
03980         
03981         return touch_any;
03982 }
03983 
03984 
03985 static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, const int UNUSED(prevmval_i[2]), const int mval_i[2], double time, float pressure)
03986 {
03987         
03988         /* Use mouse coords as floats for projection painting */
03989         float pos[2];
03990         
03991         pos[0] = (float)(mval_i[0]);
03992         pos[1] = (float)(mval_i[1]);
03993         
03994         // we may want to use this later 
03995         // brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
03996         
03997         if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) {
03998                 return 1;
03999         }
04000         else return 0;
04001 }
04002 
04003 
04004 static int project_paint_stroke(ProjPaintState *ps, BrushPainter *painter, const int prevmval_i[2], const int mval_i[2], double time, float pressure)
04005 {
04006         int a, redraw;
04007         
04008         for (a=0; a < ps->image_tot; a++)
04009                 partial_redraw_array_init(ps->projImages[a].partRedrawRect);
04010         
04011         redraw= project_paint_sub_stroke(ps, painter, prevmval_i, mval_i, time, pressure);
04012         
04013         if(project_image_refresh_tagged(ps))
04014                 return redraw;
04015         
04016         return 0;
04017 }
04018 
04019 /* Imagepaint Partial Redraw & Dirty Region */
04020 
04021 static void imapaint_clear_partial_redraw(void)
04022 {
04023         memset(&imapaintpartial, 0, sizeof(imapaintpartial));
04024 }
04025 
04026 static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h)
04027 {
04028         ImBuf *tmpibuf = NULL;
04029         int srcx= 0, srcy= 0, origx;
04030 
04031         IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
04032 
04033         if (w == 0 || h == 0)
04034                 return;
04035         
04036         if (!imapaintpartial.enabled) {
04037                 imapaintpartial.x1 = x;
04038                 imapaintpartial.y1 = y;
04039                 imapaintpartial.x2 = x+w;
04040                 imapaintpartial.y2 = y+h;
04041                 imapaintpartial.enabled = 1;
04042         }
04043         else {
04044                 imapaintpartial.x1 = MIN2(imapaintpartial.x1, x);
04045                 imapaintpartial.y1 = MIN2(imapaintpartial.y1, y);
04046                 imapaintpartial.x2 = MAX2(imapaintpartial.x2, x+w);
04047                 imapaintpartial.y2 = MAX2(imapaintpartial.y2, y+h);
04048         }
04049 
04050         w = ((x + w - 1) >> IMAPAINT_TILE_BITS);
04051         h = ((y + h - 1) >> IMAPAINT_TILE_BITS);
04052         origx = (x >> IMAPAINT_TILE_BITS);
04053         y = (y >> IMAPAINT_TILE_BITS);
04054         
04055         for (; y <= h; y++)
04056                 for (x=origx; x <= w; x++)
04057                         image_undo_push_tile(ima, ibuf, &tmpibuf, x, y);
04058 
04059         ibuf->userflags |= IB_BITMAPDIRTY;
04060         
04061         if (tmpibuf)
04062                 IMB_freeImBuf(tmpibuf);
04063 }
04064 
04065 static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
04066 {
04067         if(ibuf->rect_float)
04068                 ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
04069         
04070         if(ibuf->mipmap[0])
04071                 ibuf->userflags |= IB_MIPMAP_INVALID;
04072 
04073         /* todo: should set_tpage create ->rect? */
04074         if(texpaint || (sima && sima->lock)) {
04075                 int w = imapaintpartial.x2 - imapaintpartial.x1;
04076                 int h = imapaintpartial.y2 - imapaintpartial.y1;
04077                 GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h, !texpaint);
04078         }
04079 }
04080 
04081 /* Image Paint Operations */
04082 
04083 static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, short set, float *rgb)
04084 {
04085         if (torus) {
04086                 x %= ibuf->x;
04087                 if (x < 0) x += ibuf->x;
04088                 y %= ibuf->y;
04089                 if (y < 0) y += ibuf->y;
04090         }
04091 
04092         if (ibuf->rect_float) {
04093                 float *rrgbf = ibuf->rect_float + (ibuf->x*y + x)*4;
04094 
04095                 if (set) {
04096                         IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb);
04097                 } else {
04098                         IMAPAINT_FLOAT_RGB_COPY(rgb, rrgbf);
04099                 }
04100         }
04101         else {
04102                 char *rrgb = (char*)ibuf->rect + (ibuf->x*y + x)*4;
04103 
04104                 if (set) {
04105                         IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb)
04106                 } else {
04107                         IMAPAINT_CHAR_RGB_TO_FLOAT(rgb, rrgb)
04108                 }
04109         }
04110 }
04111 
04112 static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus)
04113 {
04114         float inrgb[3];
04115 
04116         // XXX: signed unsigned mismatch
04117         if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) {
04118                 if (torus) imapaint_ibuf_get_set_rgb(ibuf, x, y, 1, 0, inrgb);
04119                 else return 0;
04120         }
04121         else imapaint_ibuf_get_set_rgb(ibuf, x, y, 0, 0, inrgb);
04122 
04123         outrgb[0] += inrgb[0];
04124         outrgb[1] += inrgb[1];
04125         outrgb[2] += inrgb[2];
04126 
04127         return 1;
04128 }
04129 
04130 static void imapaint_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, short torus)
04131 {
04132         int x, y, count, xi, yi, xo, yo;
04133         int out_off[2], in_off[2], dim[2];
04134         float outrgb[3];
04135 
04136         dim[0] = ibufb->x;
04137         dim[1] = ibufb->y;
04138         in_off[0] = pos[0];
04139         in_off[1] = pos[1];
04140         out_off[0] = out_off[1] = 0;
04141 
04142         if (!torus) {
04143                 IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0],
04144                         &out_off[1], &dim[0], &dim[1]);
04145 
04146                 if ((dim[0] == 0) || (dim[1] == 0))
04147                         return;
04148         }
04149 
04150         for (y=0; y < dim[1]; y++) {
04151                 for (x=0; x < dim[0]; x++) {
04152                         /* get input pixel */
04153                         xi = in_off[0] + x;
04154                         yi = in_off[1] + y;
04155 
04156                         count = 1;
04157                         imapaint_ibuf_get_set_rgb(ibuf, xi, yi, torus, 0, outrgb);
04158 
04159                         count += imapaint_ibuf_add_if(ibuf, xi-1, yi-1, outrgb, torus);
04160                         count += imapaint_ibuf_add_if(ibuf, xi-1, yi  , outrgb, torus);
04161                         count += imapaint_ibuf_add_if(ibuf, xi-1, yi+1, outrgb, torus);
04162 
04163                         count += imapaint_ibuf_add_if(ibuf, xi  , yi-1, outrgb, torus);
04164                         count += imapaint_ibuf_add_if(ibuf, xi  , yi+1, outrgb, torus);
04165 
04166                         count += imapaint_ibuf_add_if(ibuf, xi+1, yi-1, outrgb, torus);
04167                         count += imapaint_ibuf_add_if(ibuf, xi+1, yi  , outrgb, torus);
04168                         count += imapaint_ibuf_add_if(ibuf, xi+1, yi+1, outrgb, torus);
04169 
04170                         outrgb[0] /= count;
04171                         outrgb[1] /= count;
04172                         outrgb[2] /= count;
04173 
04174                         /* write into brush buffer */
04175                         xo = out_off[0] + x;
04176                         yo = out_off[1] + y;
04177                         imapaint_ibuf_get_set_rgb(ibufb, xo, yo, 0, 1, outrgb);
04178                 }
04179         }
04180 }
04181 
04182 static void imapaint_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height)
04183 {
04184         region->destx= destx;
04185         region->desty= desty;
04186         region->srcx= srcx;
04187         region->srcy= srcy;
04188         region->width= width;
04189         region->height= height;
04190 }
04191 
04192 static int imapaint_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf)
04193 {
04194         int destx= region->destx;
04195         int desty= region->desty;
04196         int srcx= region->srcx;
04197         int srcy= region->srcy;
04198         int width= region->width;
04199         int height= region->height;
04200         int origw, origh, w, h, tot= 0;
04201 
04202         /* convert destination and source coordinates to be within image */
04203         destx = destx % dbuf->x;
04204         if (destx < 0) destx += dbuf->x;
04205         desty = desty % dbuf->y;
04206         if (desty < 0) desty += dbuf->y;
04207         srcx = srcx % sbuf->x;
04208         if (srcx < 0) srcx += sbuf->x;
04209         srcy = srcy % sbuf->y;
04210         if (srcy < 0) srcy += sbuf->y;
04211 
04212         /* clip width of blending area to destination imbuf, to avoid writing the
04213            same pixel twice */
04214         origw = w = (width > dbuf->x)? dbuf->x: width;
04215         origh = h = (height > dbuf->y)? dbuf->y: height;
04216 
04217         /* clip within image */
04218         IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h);
04219         imapaint_set_region(&region[tot++], destx, desty, srcx, srcy, w, h);
04220 
04221         /* do 3 other rects if needed */
04222         if (w < origw)
04223                 imapaint_set_region(&region[tot++], (destx+w)%dbuf->x, desty, (srcx+w)%sbuf->x, srcy, origw-w, h);
04224         if (h < origh)
04225                 imapaint_set_region(&region[tot++], destx, (desty+h)%dbuf->y, srcx, (srcy+h)%sbuf->y, w, origh-h);
04226         if ((w < origw) && (h < origh))
04227                 imapaint_set_region(&region[tot++], (destx+w)%dbuf->x, (desty+h)%dbuf->y, (srcx+w)%sbuf->x, (srcy+h)%sbuf->y, origw-w, origh-h);
04228         
04229         return tot;
04230 }
04231 
04232 static void imapaint_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos)
04233 {
04234         ImagePaintRegion region[4];
04235         int a, tot;
04236 
04237         imapaint_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y);
04238         tot= imapaint_torus_split_region(region, ibufb, ibuf);
04239 
04240         for(a=0; a<tot; a++)
04241                 IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty,
04242                         region[a].srcx, region[a].srcy,
04243                         region[a].width, region[a].height, IMB_BLEND_COPY_RGB);
04244 }
04245 
04246 static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos)
04247 {
04248         /* note: allocImbuf returns zero'd memory, so regions outside image will
04249            have zero alpha, and hence not be blended onto the image */
04250         int w=ibufb->x, h=ibufb->y, destx=0, desty=0, srcx=pos[0], srcy=pos[1];
04251         ImBuf *clonebuf= IMB_allocImBuf(w, h, ibufb->depth, ibufb->flags);
04252 
04253         IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h);
04254         IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h,
04255                 IMB_BLEND_COPY_RGB);
04256         IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h,
04257                 IMB_BLEND_COPY_ALPHA);
04258 
04259         return clonebuf;
04260 }
04261 
04262 static void imapaint_convert_brushco(ImBuf *ibufb, float *pos, int *ipos)
04263 {
04264         ipos[0]= (int)floorf((pos[0] - ibufb->x/2) + 1.0f);
04265         ipos[1]= (int)floorf((pos[1] - ibufb->y/2) + 1.0f);
04266 }
04267 
04268 /* dosnt run for projection painting
04269  * only the old style painting in the 3d view */
04270 static int imapaint_paint_op(void *state, ImBuf *ibufb, float *lastpos, float *pos)
04271 {
04272         ImagePaintState *s= ((ImagePaintState*)state);
04273         ImBuf *clonebuf= NULL, *frombuf;
04274         ImagePaintRegion region[4];
04275         short torus= s->brush->flag & BRUSH_TORUS;
04276         short blend= s->blend;
04277         float *offset= s->brush->clone.offset;
04278         float liftpos[2];
04279         int bpos[2], blastpos[2], bliftpos[2];
04280         int a, tot;
04281 
04282         imapaint_convert_brushco(ibufb, pos, bpos);
04283 
04284         /* lift from canvas */
04285         if(s->tool == PAINT_TOOL_SOFTEN) {
04286                 imapaint_lift_soften(s->canvas, ibufb, bpos, torus);
04287         }
04288         else if(s->tool == PAINT_TOOL_SMEAR) {
04289                 if (lastpos[0]==pos[0] && lastpos[1]==pos[1])
04290                         return 0;
04291 
04292                 imapaint_convert_brushco(ibufb, lastpos, blastpos);
04293                 imapaint_lift_smear(s->canvas, ibufb, blastpos);
04294         }
04295         else if(s->tool == PAINT_TOOL_CLONE && s->clonecanvas) {
04296                 liftpos[0]= pos[0] - offset[0]*s->canvas->x;
04297                 liftpos[1]= pos[1] - offset[1]*s->canvas->y;
04298 
04299                 imapaint_convert_brushco(ibufb, liftpos, bliftpos);
04300                 clonebuf= imapaint_lift_clone(s->clonecanvas, ibufb, bliftpos);
04301         }
04302 
04303         frombuf= (clonebuf)? clonebuf: ibufb;
04304 
04305         if(torus) {
04306                 imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
04307                 tot= imapaint_torus_split_region(region, s->canvas, frombuf);
04308         }
04309         else {
04310                 imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y);
04311                 tot= 1;
04312         }
04313 
04314         /* blend into canvas */
04315         for(a=0; a<tot; a++) {
04316                 imapaint_dirty_region(s->image, s->canvas,
04317                         region[a].destx, region[a].desty,
04318                         region[a].width, region[a].height);
04319                 
04320                 IMB_rectblend(s->canvas, frombuf,
04321                         region[a].destx, region[a].desty,
04322                         region[a].srcx, region[a].srcy,
04323                         region[a].width, region[a].height, blend);
04324         }
04325 
04326         if(clonebuf) IMB_freeImBuf(clonebuf);
04327 
04328         return 1;
04329 }
04330 
04331 /* 3D TexturePaint */
04332 
04333 static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float *uv)
04334 {
04335         float d1[2], d2[2];
04336         float mismatch = len_v2v2(fwuv, uv);
04337         float len1 = len_v2v2(prevuv, fwuv);
04338         float len2 = len_v2v2(bkuv, uv);
04339 
04340         sub_v2_v2v2(d1, fwuv, prevuv);
04341         sub_v2_v2v2(d2, uv, bkuv);
04342 
04343         return ((dot_v2v2(d1, d2) < 0.0f) || (mismatch > MAX2(len1, len2)*2));
04344 }
04345 
04346 /* ImagePaint Common */
04347 
04348 static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
04349 {
04350         ImBuf *ibuf= BKE_image_get_ibuf(ima, s->sima? &s->sima->iuser: NULL);
04351         
04352         /* verify that we can paint and set canvas */
04353         if(ima==NULL) {
04354                 return 0;
04355         }
04356         else if(ima->packedfile && ima->rr) {
04357                 s->warnpackedfile = ima->id.name + 2;
04358                 return 0;
04359         }       
04360         else if(ibuf && ibuf->channels!=4) {
04361                 s->warnmultifile = ima->id.name + 2;
04362                 return 0;
04363         }
04364         else if(!ibuf || !(ibuf->rect || ibuf->rect_float))
04365                 return 0;
04366 
04367         s->image= ima;
04368         s->canvas= ibuf;
04369 
04370         /* set clone canvas */
04371         if(s->tool == PAINT_TOOL_CLONE) {
04372                 ima= s->brush->clone.image;
04373                 ibuf= BKE_image_get_ibuf(ima, s->sima? &s->sima->iuser: NULL);
04374                 
04375                 if(!ima || !ibuf || !(ibuf->rect || ibuf->rect_float))
04376                         return 0;
04377 
04378                 s->clonecanvas= ibuf;
04379 
04380                 /* temporarily add float rect for cloning */
04381                 if(s->canvas->rect_float && !s->clonecanvas->rect_float) {
04382                         int profile = IB_PROFILE_NONE;
04383                         
04384                         /* Don't want to color manage, but don't disturb existing profiles */
04385                         SWAP(int, s->clonecanvas->profile, profile);
04386 
04387                         IMB_float_from_rect(s->clonecanvas);
04388                         s->clonefreefloat= 1;
04389                         
04390                         SWAP(int, s->clonecanvas->profile, profile);
04391                 }
04392                 else if(!s->canvas->rect_float && !s->clonecanvas->rect)
04393                         IMB_rect_from_float(s->clonecanvas);
04394         }
04395 
04396         return 1;
04397 }
04398 
04399 static void imapaint_canvas_free(ImagePaintState *s)
04400 {
04401         if (s->clonefreefloat)
04402                 imb_freerectfloatImBuf(s->clonecanvas);
04403 }
04404 
04405 static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure)
04406 {
04407         ImBuf *ibuf= BKE_image_get_ibuf(image, s->sima? &s->sima->iuser: NULL);
04408         float pos[2];
04409 
04410         if(!ibuf)
04411                 return 0;
04412 
04413         pos[0] = uv[0]*ibuf->x;
04414         pos[1] = uv[1]*ibuf->y;
04415 
04416         brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0);
04417 
04418         if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) {
04419                 if (update)
04420                         imapaint_image_update(s->sima, image, ibuf, texpaint);
04421                 return 1;
04422         }
04423         else return 0;
04424 }
04425 
04426 static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure)
04427 {
04428         Image *newimage = NULL;
04429         float fwuv[2], bkuv[2], newuv[2];
04430         unsigned int newfaceindex;
04431         int breakstroke = 0, redraw = 0;
04432 
04433         if (texpaint) {
04434                 /* pick new face and image */
04435                 if (    imapaint_pick_face(vc, s->me, mval, &newfaceindex) &&
04436                                 ((s->me->editflag & ME_EDIT_PAINT_MASK)==0 || (s->me->mface+newfaceindex)->flag & ME_FACE_SEL)
04437                 ) {
04438                         ImBuf *ibuf;
04439                         
04440                         newimage = (s->me->mtface+newfaceindex)->tpage;
04441                         ibuf= BKE_image_get_ibuf(newimage, s->sima? &s->sima->iuser: NULL);
04442 
04443                         if(ibuf && ibuf->rect)
04444                                 imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv);
04445                         else {
04446                                 newimage = NULL;
04447                                 newuv[0] = newuv[1] = 0.0f;
04448                         }
04449                 }
04450                 else
04451                         newuv[0] = newuv[1] = 0.0f;
04452 
04453                 /* see if stroke is broken, and if so finish painting in old position */
04454                 if (s->image) {
04455                         imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv);
04456                         imapaint_pick_uv(s->scene, s->ob, newfaceindex, prevmval, bkuv);
04457 
04458                         if (newimage == s->image)
04459                                 breakstroke= texpaint_break_stroke(s->uv, fwuv, bkuv, newuv);
04460                         else
04461                                 breakstroke= 1;
04462                 }
04463                 else
04464                         fwuv[0]= fwuv[1]= 0.0f;
04465 
04466                 if (breakstroke) {
04467                         imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv);
04468                         redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint,
04469                                 fwuv, time, 1, pressure);
04470                         imapaint_clear_partial_redraw();
04471                         brush_painter_break_stroke(painter);
04472                 }
04473 
04474                 /* set new canvas */
04475                 if (newimage && (newimage != s->image))
04476                         if (!imapaint_canvas_set(s, newimage))
04477                                 newimage = NULL;
04478 
04479                 /* paint in new image */
04480                 if (newimage) {
04481                         if (breakstroke)
04482                                 redraw|= imapaint_paint_sub_stroke(s, painter, newimage,
04483                                         texpaint, bkuv, time, 0, pressure);
04484                         redraw|= imapaint_paint_sub_stroke(s, painter, newimage, texpaint,
04485                                 newuv, time, 1, pressure);
04486                 }
04487 
04488                 /* update state */
04489                 s->image = newimage;
04490                 s->faceindex = newfaceindex;
04491                 s->uv[0] = newuv[0];
04492                 s->uv[1] = newuv[1];
04493         }
04494         else {
04495                 UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]);
04496                 redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, newuv,
04497                         time, 1, pressure);
04498         }
04499 
04500         if (redraw)
04501                 imapaint_clear_partial_redraw();
04502 
04503         return redraw;
04504 }
04505 
04506 /************************ image paint poll ************************/
04507 
04508 static Brush *image_paint_brush(bContext *C)
04509 {
04510         Scene *scene= CTX_data_scene(C);
04511         ToolSettings *settings= scene->toolsettings;
04512 
04513         return paint_brush(&settings->imapaint.paint);
04514 }
04515 
04516 static int image_paint_poll(bContext *C)
04517 {
04518         Object *obact = CTX_data_active_object(C);
04519 
04520         if(!image_paint_brush(C))
04521                 return 0;
04522 
04523         if((obact && obact->mode & OB_MODE_TEXTURE_PAINT) && CTX_wm_region_view3d(C)) {
04524                 return 1;
04525         }
04526         else {
04527                 SpaceImage *sima= CTX_wm_space_image(C);
04528 
04529                 if(sima) {
04530                         ARegion *ar= CTX_wm_region(C);
04531 
04532                         if((sima->flag & SI_DRAWTOOL) && ar->regiontype==RGN_TYPE_WINDOW)
04533                                 return 1;
04534                 }
04535         }
04536 
04537         return 0;
04538 }
04539 
04540 static int image_paint_3d_poll(bContext *C)
04541 {
04542         if(CTX_wm_region_view3d(C))
04543                 return image_paint_poll(C);
04544         
04545         return 0;
04546 }
04547 
04548 static int image_paint_2d_clone_poll(bContext *C)
04549 {
04550         Brush *brush= image_paint_brush(C);
04551 
04552         if(!CTX_wm_region_view3d(C) && image_paint_poll(C))
04553                 if(brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE))
04554                         if(brush->clone.image)
04555                                 return 1;
04556         
04557         return 0;
04558 }
04559 
04560 /************************ paint operator ************************/
04561 
04562 typedef enum PaintMode {
04563         PAINT_MODE_2D,
04564         PAINT_MODE_3D,
04565         PAINT_MODE_3D_PROJECT
04566 } PaintMode;
04567 
04568 typedef struct PaintOperation {
04569         PaintMode mode;
04570 
04571         BrushPainter *painter;
04572         ImagePaintState s;
04573         ProjPaintState ps;
04574 
04575         int first;
04576         int prevmouse[2];
04577         float prev_pressure; /* need this since we dont get tablet events for pressure change */
04578         int orig_brush_size;
04579         double starttime;
04580 
04581         ViewContext vc;
04582         wmTimer *timer;
04583 
04584         short restore_projection;
04585 } PaintOperation;
04586 
04587 static void paint_redraw(bContext *C, ImagePaintState *s, int final)
04588 {
04589         if(final) {
04590                 if(s->image)
04591                         GPU_free_image(s->image);
04592 
04593                 /* compositor listener deals with updating */
04594                 WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, s->image);
04595         }
04596         else {
04597                 if(!s->sima || !s->sima->lock)
04598                         ED_region_tag_redraw(CTX_wm_region(C));
04599                 else
04600                         WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, s->image);
04601         }
04602 }
04603 
04604 /* initialize project paint settings from context */
04605 static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps)
04606 {
04607         Scene *scene= CTX_data_scene(C);
04608         ToolSettings *settings= scene->toolsettings;
04609         Brush *brush= paint_brush(&settings->imapaint.paint);
04610 
04611         /* brush */
04612         ps->brush = brush;
04613         ps->tool = brush->imagepaint_tool;
04614         ps->blend = brush->blend;
04615 
04616         ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0;
04617         ps->is_texbrush = (brush->mtex.tex) ? 1 : 0;
04618 
04619 
04620         /* these can be NULL */
04621         ps->v3d= CTX_wm_view3d(C);
04622         ps->rv3d= CTX_wm_region_view3d(C);
04623         ps->ar= CTX_wm_region(C);
04624 
04625         ps->scene= scene;
04626         ps->ob= ob; /* allow override of active object */
04627 
04628         /* setup projection painting data */
04629         ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1;
04630         ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1;
04631         ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;
04632 
04633         if (ps->tool == PAINT_TOOL_CLONE)
04634                 ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE);
04635 
04636         ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0;
04637         ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0;
04638 
04639 
04640 #ifndef PROJ_DEBUG_NOSEAMBLEED
04641         ps->seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */
04642 #endif
04643 
04644         if(ps->do_mask_normal) {
04645                 ps->normal_angle_inner = settings->imapaint.normal_angle;
04646                 ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f;
04647         }
04648         else {
04649                 ps->normal_angle_inner= ps->normal_angle= settings->imapaint.normal_angle;
04650         }
04651 
04652         ps->normal_angle_inner *=       (float)(M_PI_2 / 90);
04653         ps->normal_angle *=                     (float)(M_PI_2 / 90);
04654         ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner;
04655 
04656         if(ps->normal_angle_range <= 0.0f)
04657                 ps->do_mask_normal = 0; /* no need to do blending */
04658 }
04659 
04660 static void paint_brush_init_tex(Brush *brush)
04661 {
04662         /* init mtex nodes */ 
04663         if(brush) {
04664                 MTex *mtex= &brush->mtex;
04665                 if(mtex->tex && mtex->tex->nodetree)
04666                         ntreeBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
04667         }
04668         
04669 }
04670 
04671 static int texture_paint_init(bContext *C, wmOperator *op)
04672 {
04673         Scene *scene= CTX_data_scene(C);
04674         ToolSettings *settings= scene->toolsettings;
04675         Brush *brush= paint_brush(&settings->imapaint.paint);
04676         PaintOperation *pop= MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
04677 
04678         pop->first= 1;
04679         op->customdata= pop;
04680         
04681         /* XXX: Soften tool does not support projection painting atm, so just disable
04682                 projection for this brush */
04683         if(brush->imagepaint_tool == PAINT_TOOL_SOFTEN) {
04684                 settings->imapaint.flag |= IMAGEPAINT_PROJECT_DISABLE;
04685                 pop->restore_projection = 1;
04686         }
04687 
04688         /* initialize from context */
04689         if(CTX_wm_region_view3d(C)) {
04690                 pop->mode= PAINT_MODE_3D;
04691 
04692                 if(!(settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE))
04693                         pop->mode= PAINT_MODE_3D_PROJECT;
04694                 else
04695                         view3d_set_viewcontext(C, &pop->vc);
04696         }
04697         else {
04698                 pop->s.sima= CTX_wm_space_image(C);
04699                 pop->s.v2d= &CTX_wm_region(C)->v2d;
04700         }
04701 
04702         pop->s.scene= scene;
04703         pop->s.screen= CTX_wm_screen(C);
04704 
04705         pop->s.brush = brush;
04706         pop->s.tool = brush->imagepaint_tool;
04707         if(pop->mode == PAINT_MODE_3D && (pop->s.tool == PAINT_TOOL_CLONE))
04708                 pop->s.tool = PAINT_TOOL_DRAW;
04709         pop->s.blend = brush->blend;
04710         pop->orig_brush_size= brush_size(brush);
04711 
04712         if(pop->mode != PAINT_MODE_2D) {
04713                 pop->s.ob = OBACT;
04714                 pop->s.me = get_mesh(pop->s.ob);
04715                 if (!pop->s.me) return 0;
04716         }
04717         else {
04718                 pop->s.image = pop->s.sima->image;
04719 
04720                 if(!imapaint_canvas_set(&pop->s, pop->s.image)) {
04721                         if(pop->s.warnmultifile)
04722                                 BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint");
04723                         if(pop->s.warnpackedfile)
04724                                 BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted");
04725 
04726                         return 0;
04727                 }
04728         }
04729         
04730         paint_brush_init_tex(pop->s.brush);
04731         
04732         /* note, if we have no UVs on the derived mesh, then we must return here */
04733         if(pop->mode == PAINT_MODE_3D_PROJECT) {
04734 
04735                 /* initialize all data from the context */
04736                 project_state_init(C, OBACT, &pop->ps);
04737                 
04738                 paint_brush_init_tex(pop->ps.brush);
04739 
04740                 pop->ps.source= PROJ_SRC_VIEW;
04741 
04742                 if (pop->ps.ob==NULL || !(pop->ps.ob->lay & pop->ps.v3d->lay))
04743                         return 0;
04744 
04745                 /* Dont allow brush size below 2 */
04746                 if (brush_size(brush) < 2)
04747                         brush_set_size(brush, 2);
04748 
04749                 /* allocate and initialize spacial data structures */
04750                 project_paint_begin(&pop->ps);
04751                 
04752                 if(pop->ps.dm==NULL)
04753                         return 0;
04754         }
04755         
04756         settings->imapaint.flag |= IMAGEPAINT_DRAWING;
04757         undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
04758                 image_undo_restore, image_undo_free);
04759 
04760         /* create painter */
04761         pop->painter= brush_painter_new(pop->s.brush);
04762 
04763         return 1;
04764 }
04765 
04766 static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
04767 {
04768         PaintOperation *pop= op->customdata;
04769         float time, mousef[2];
04770         float pressure;
04771         int mouse[2], redraw;
04772 
04773         RNA_float_get_array(itemptr, "mouse", mousef);
04774         mouse[0] = (int)(mousef[0]);
04775         mouse[1] = (int)(mousef[1]);
04776         time= RNA_float_get(itemptr, "time");
04777         pressure= RNA_float_get(itemptr, "pressure");
04778 
04779         if(pop->first)
04780                 project_paint_begin_clone(&pop->ps, mouse);
04781 
04782         if(pop->mode == PAINT_MODE_3D)
04783                 view3d_operator_needs_opengl(C);
04784 
04785         if(pop->mode == PAINT_MODE_3D_PROJECT) {
04786                 redraw= project_paint_stroke(&pop->ps, pop->painter, pop->prevmouse, mouse, time, pressure);
04787                 pop->prevmouse[0]= mouse[0];
04788                 pop->prevmouse[1]= mouse[1];
04789 
04790         }
04791         else { 
04792                 redraw= imapaint_paint_stroke(&pop->vc, &pop->s, pop->painter, pop->mode == PAINT_MODE_3D, pop->prevmouse, mouse, time, pressure);
04793                 pop->prevmouse[0]= mouse[0];
04794                 pop->prevmouse[1]= mouse[1];
04795         }
04796 
04797         if(redraw)
04798                 paint_redraw(C, &pop->s, 0);
04799 
04800         pop->first= 0;
04801 }
04802 
04803 static void paint_brush_exit_tex(Brush *brush)
04804 {
04805         if(brush) {
04806                 MTex *mtex= &brush->mtex;
04807                 if(mtex->tex && mtex->tex->nodetree)
04808                         ntreeEndExecTree(mtex->tex->nodetree);
04809         }       
04810 }
04811 
04812 static void paint_exit(bContext *C, wmOperator *op)
04813 {
04814         Scene *scene= CTX_data_scene(C);
04815         ToolSettings *settings= scene->toolsettings;
04816         PaintOperation *pop= op->customdata;
04817 
04818         if(pop->timer)
04819                 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
04820 
04821         if(pop->restore_projection)
04822                 settings->imapaint.flag &= ~IMAGEPAINT_PROJECT_DISABLE;
04823 
04824         paint_brush_exit_tex(pop->s.brush);
04825         
04826         settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
04827         imapaint_canvas_free(&pop->s);
04828         brush_painter_free(pop->painter);
04829 
04830         if(pop->mode == PAINT_MODE_3D_PROJECT) {
04831                 brush_set_size(pop->ps.brush, pop->orig_brush_size);
04832                 paint_brush_exit_tex(pop->ps.brush);
04833                 
04834                 project_paint_end(&pop->ps);
04835         }
04836         
04837         paint_redraw(C, &pop->s, 1);
04838         undo_paint_push_end(UNDO_PAINT_IMAGE);
04839         
04840         if(pop->s.warnmultifile)
04841                 BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
04842         if(pop->s.warnpackedfile)
04843                 BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
04844 
04845         MEM_freeN(pop);
04846 }
04847 
04848 static int paint_exec(bContext *C, wmOperator *op)
04849 {
04850         if(!texture_paint_init(C, op)) {
04851                 MEM_freeN(op->customdata);
04852                 return OPERATOR_CANCELLED;
04853         }
04854 
04855         RNA_BEGIN(op->ptr, itemptr, "stroke") {
04856                 paint_apply(C, op, &itemptr);
04857         }
04858         RNA_END;
04859 
04860         paint_exit(C, op);
04861 
04862         return OPERATOR_FINISHED;
04863 }
04864 
04865 static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
04866 {
04867         PaintOperation *pop= op->customdata;
04868         wmTabletData *wmtab;
04869         PointerRNA itemptr;
04870         float pressure, mousef[2];
04871         double time;
04872         int tablet;
04873 
04874         time= PIL_check_seconds_timer();
04875 
04876         tablet= 0;
04877         pressure= 0;
04878         pop->s.blend= pop->s.brush->blend;
04879 
04880         if(event->custom == EVT_DATA_TABLET) {
04881                 wmtab= event->customdata;
04882 
04883                 tablet= (wmtab->Active != EVT_TABLET_NONE);
04884                 pressure= wmtab->Pressure;
04885                 if(wmtab->Active == EVT_TABLET_ERASER)
04886                         pop->s.blend= IMB_BLEND_ERASE_ALPHA;
04887         }
04888         else /* otherwise airbrush becomes 1.0 pressure instantly */
04889                 pressure= pop->prev_pressure ? pop->prev_pressure : 1.0f;
04890 
04891         if(pop->first) {
04892                 pop->prevmouse[0]= event->mval[0];
04893                 pop->prevmouse[1]= event->mval[1];
04894                 pop->starttime= time;
04895 
04896                 /* special exception here for too high pressure values on first touch in
04897                    windows for some tablets, then we just skip first touch ..  */
04898                 if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || brush_use_alpha_pressure(pop->s.brush) || brush_use_size_pressure(pop->s.brush)))
04899                         return;
04900 
04901                 /* This can be removed once fixed properly in
04902                  brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) 
04903                  at zero pressure we should do nothing 1/2^12 is .0002 which is the sensitivity of the most sensitive pen tablet available*/
04904                 if (tablet && (pressure < .0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || brush_use_alpha_pressure(pop->s.brush) || brush_use_size_pressure(pop->s.brush)))
04905                         return;
04906         
04907         }
04908 
04909         /* fill in stroke */
04910         RNA_collection_add(op->ptr, "stroke", &itemptr);
04911 
04912         mousef[0] = (float)(event->mval[0]);
04913         mousef[1] = (float)(event->mval[1]);
04914         RNA_float_set_array(&itemptr, "mouse", mousef);
04915         RNA_float_set(&itemptr, "time", (float)(time - pop->starttime));
04916         RNA_float_set(&itemptr, "pressure", pressure);
04917 
04918         /* apply */
04919         paint_apply(C, op, &itemptr);
04920 
04921         pop->prev_pressure= pressure;
04922 }
04923 
04924 static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event)
04925 {
04926         PaintOperation *pop;
04927 
04928         if(!texture_paint_init(C, op)) {
04929                 MEM_freeN(op->customdata);
04930                 return OPERATOR_CANCELLED;
04931         }
04932         
04933         paint_apply_event(C, op, event);
04934 
04935         pop= op->customdata;
04936         WM_event_add_modal_handler(C, op);
04937 
04938         if(pop->s.brush->flag & BRUSH_AIRBRUSH)
04939                 pop->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
04940 
04941         return OPERATOR_RUNNING_MODAL;
04942 }
04943 
04944 static int paint_modal(bContext *C, wmOperator *op, wmEvent *event)
04945 {
04946         PaintOperation *pop= op->customdata;
04947 
04948         switch(event->type) {
04949                 case LEFTMOUSE:
04950                 case MIDDLEMOUSE:
04951                 case RIGHTMOUSE: // XXX hardcoded
04952                         paint_exit(C, op);
04953                         return OPERATOR_FINISHED;
04954                 case MOUSEMOVE:
04955                 case INBETWEEN_MOUSEMOVE:
04956                         paint_apply_event(C, op, event);
04957                         break;
04958                 case TIMER:
04959                         if(event->customdata == pop->timer)
04960                                 paint_apply_event(C, op, event);
04961                         break;
04962         }
04963 
04964         return OPERATOR_RUNNING_MODAL;
04965 }
04966 
04967 static int paint_cancel(bContext *C, wmOperator *op)
04968 {
04969         paint_exit(C, op);
04970 
04971         return OPERATOR_CANCELLED;
04972 }
04973 
04974 void PAINT_OT_image_paint(wmOperatorType *ot)
04975 {
04976         /* identifiers */
04977         ot->name= "Image Paint";
04978         ot->idname= "PAINT_OT_image_paint";
04979         
04980         /* api callbacks */
04981         ot->exec= paint_exec;
04982         ot->invoke= paint_invoke;
04983         ot->modal= paint_modal;
04984         ot->cancel= paint_cancel;
04985         ot->poll= image_paint_poll;
04986 
04987         /* flags */
04988         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
04989 
04990         /* properties */
04991         RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
04992 }
04993 
04994 static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
04995 {
04996         RegionView3D *rv3d= CTX_wm_region_view3d(C);
04997 
04998         if(!rv3d) {
04999                 SpaceImage *sima= CTX_wm_space_image(C);
05000                 ARegion *ar= CTX_wm_region(C);
05001                 
05002                 ED_space_image_zoom(sima, ar, zoomx, zoomy);
05003 
05004                 return 1;
05005         }
05006 
05007         *zoomx = *zoomy = 1;
05008 
05009         return 0;
05010 }
05011 
05012 /************************ cursor drawing *******************************/
05013 
05014 static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
05015 {
05016 #define PX_SIZE_FADE_MAX 12.0f
05017 #define PX_SIZE_FADE_MIN 4.0f
05018 
05019         Brush *brush= image_paint_brush(C);
05020         Paint *paint= paint_get_active(CTX_data_scene(C));
05021 
05022         if(paint && brush && paint->flags & PAINT_SHOW_BRUSH) {
05023                 float zoomx, zoomy;
05024                 const float size= (float)brush_size(brush);
05025                 const short use_zoom= get_imapaint_zoom(C, &zoomx, &zoomy);
05026                 const float pixel_size= MAX2(size * zoomx, size * zoomy);
05027                 float alpha= 0.5f;
05028 
05029                 /* fade out the brush (cheap trick to work around brush interfearing with sampling [#])*/
05030                 if(pixel_size < PX_SIZE_FADE_MIN) {
05031                         return;
05032                 }
05033                 else if (pixel_size < PX_SIZE_FADE_MAX) {
05034                         alpha *= (pixel_size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN);
05035                 }
05036 
05037                 glPushMatrix();
05038 
05039                 glTranslatef((float)x, (float)y, 0.0f);
05040 
05041                 if(use_zoom)
05042                         glScalef(zoomx, zoomy, 1.0f);
05043 
05044                 glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha);
05045                 glEnable( GL_LINE_SMOOTH );
05046                 glEnable(GL_BLEND);
05047                 glutil_draw_lined_arc(0, (float)(M_PI*2.0), size, 40);
05048                 glDisable(GL_BLEND);
05049                 glDisable( GL_LINE_SMOOTH );
05050 
05051                 glPopMatrix();
05052         }
05053 #undef PX_SIZE_FADE_MAX
05054 #undef PX_SIZE_FADE_MIN
05055 }
05056 
05057 static void toggle_paint_cursor(bContext *C, int enable)
05058 {
05059         ToolSettings *settings= CTX_data_scene(C)->toolsettings;
05060 
05061         if(settings->imapaint.paintcursor && !enable) {
05062                 WM_paint_cursor_end(CTX_wm_manager(C), settings->imapaint.paintcursor);
05063                 settings->imapaint.paintcursor = NULL;
05064         }
05065         else if(enable)
05066                 settings->imapaint.paintcursor= WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, brush_drawcursor, NULL);
05067 }
05068 
05069 /* enable the paint cursor if it isn't already.
05070 
05071    purpose is to make sure the paint cursor is shown if paint
05072    mode is enabled in the image editor. the paint poll will
05073    ensure that the cursor is hidden when not in paint mode */
05074 void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings)
05075 {
05076         ImagePaintSettings *imapaint = &settings->imapaint;
05077 
05078         if(!imapaint->paintcursor) {
05079                 imapaint->paintcursor =
05080                         WM_paint_cursor_activate(wm, image_paint_poll,
05081                                                  brush_drawcursor, NULL);
05082         }
05083 }
05084 
05085 /************************ grab clone operator ************************/
05086 
05087 typedef struct GrabClone {
05088         float startoffset[2];
05089         int startx, starty;
05090 } GrabClone;
05091 
05092 static void grab_clone_apply(bContext *C, wmOperator *op)
05093 {
05094         Brush *brush= image_paint_brush(C);
05095         float delta[2];
05096 
05097         RNA_float_get_array(op->ptr, "delta", delta);
05098         add_v2_v2(brush->clone.offset, delta);
05099         ED_region_tag_redraw(CTX_wm_region(C));
05100 }
05101 
05102 static int grab_clone_exec(bContext *C, wmOperator *op)
05103 {
05104         grab_clone_apply(C, op);
05105 
05106         return OPERATOR_FINISHED;
05107 }
05108 
05109 static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event)
05110 {
05111         Brush *brush= image_paint_brush(C);
05112         GrabClone *cmv;
05113 
05114         cmv= MEM_callocN(sizeof(GrabClone), "GrabClone");
05115         copy_v2_v2(cmv->startoffset, brush->clone.offset);
05116         cmv->startx= event->x;
05117         cmv->starty= event->y;
05118         op->customdata= cmv;
05119 
05120         WM_event_add_modal_handler(C, op);
05121 
05122         return OPERATOR_RUNNING_MODAL;
05123 }
05124 
05125 static int grab_clone_modal(bContext *C, wmOperator *op, wmEvent *event)
05126 {
05127         Brush *brush= image_paint_brush(C);
05128         ARegion *ar= CTX_wm_region(C);
05129         GrabClone *cmv= op->customdata;
05130         float startfx, startfy, fx, fy, delta[2];
05131         int xmin= ar->winrct.xmin, ymin= ar->winrct.ymin;
05132 
05133         switch(event->type) {
05134                 case LEFTMOUSE:
05135                 case MIDDLEMOUSE:
05136                 case RIGHTMOUSE: // XXX hardcoded
05137                         MEM_freeN(op->customdata);
05138                         return OPERATOR_FINISHED;
05139                 case MOUSEMOVE:
05140                         /* mouse moved, so move the clone image */
05141                         UI_view2d_region_to_view(&ar->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
05142                         UI_view2d_region_to_view(&ar->v2d, event->x - xmin, event->y - ymin, &fx, &fy);
05143 
05144                         delta[0]= fx - startfx;
05145                         delta[1]= fy - startfy;
05146                         RNA_float_set_array(op->ptr, "delta", delta);
05147 
05148                         copy_v2_v2(brush->clone.offset, cmv->startoffset);
05149 
05150                         grab_clone_apply(C, op);
05151                         break;
05152         }
05153 
05154         return OPERATOR_RUNNING_MODAL;
05155 }
05156 
05157 static int grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
05158 {
05159         MEM_freeN(op->customdata);
05160         return OPERATOR_CANCELLED;
05161 }
05162 
05163 void PAINT_OT_grab_clone(wmOperatorType *ot)
05164 {
05165         /* identifiers */
05166         ot->name= "Grab Clone";
05167         ot->idname= "PAINT_OT_grab_clone";
05168         
05169         /* api callbacks */
05170         ot->exec= grab_clone_exec;
05171         ot->invoke= grab_clone_invoke;
05172         ot->modal= grab_clone_modal;
05173         ot->cancel= grab_clone_cancel;
05174         ot->poll= image_paint_2d_clone_poll;
05175 
05176         /* flags */
05177         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
05178 
05179         /* properties */
05180         RNA_def_float_vector(ot->srna, "delta", 2, NULL, -FLT_MAX, FLT_MAX, "Delta", "Delta offset of clone image in 0.0..1.0 coordinates.", -1.0f, 1.0f);
05181 }
05182 
05183 /******************** sample color operator ********************/
05184 
05185 static int sample_color_exec(bContext *C, wmOperator *op)
05186 {
05187         Scene *scene= CTX_data_scene(C);
05188         Brush *brush= image_paint_brush(C);
05189         ARegion *ar= CTX_wm_region(C);
05190         int location[2];
05191 
05192         RNA_int_get_array(op->ptr, "location", location);
05193         paint_sample_color(scene, ar, location[0], location[1]);
05194 
05195         WM_event_add_notifier(C, NC_BRUSH|NA_EDITED, brush);
05196         
05197         return OPERATOR_FINISHED;
05198 }
05199 
05200 static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event)
05201 {
05202         RNA_int_set_array(op->ptr, "location", event->mval);
05203         sample_color_exec(C, op);
05204 
05205         WM_event_add_modal_handler(C, op);
05206 
05207         return OPERATOR_RUNNING_MODAL;
05208 }
05209 
05210 static int sample_color_modal(bContext *C, wmOperator *op, wmEvent *event)
05211 {
05212         switch(event->type) {
05213                 case LEFTMOUSE:
05214                 case RIGHTMOUSE: // XXX hardcoded
05215                         return OPERATOR_FINISHED;
05216                 case MOUSEMOVE:
05217                         RNA_int_set_array(op->ptr, "location", event->mval);
05218                         sample_color_exec(C, op);
05219                         break;
05220         }
05221 
05222         return OPERATOR_RUNNING_MODAL;
05223 }
05224 
05225 /* same as image_paint_poll but fail when face mask mode is enabled */
05226 static int image_paint_sample_color_poll(bContext *C)
05227 {
05228         if(image_paint_poll(C)) {
05229                 if(CTX_wm_view3d(C)) {
05230                         Object *obact = CTX_data_active_object(C);
05231                         if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
05232                                 Mesh *me= get_mesh(obact);
05233                                 if(me) {
05234                                         return !(me->editflag & ME_EDIT_PAINT_MASK);
05235                                 }
05236                         }
05237                 }
05238 
05239                 return 1;
05240         }
05241 
05242         return 0;
05243 }
05244 
05245 void PAINT_OT_sample_color(wmOperatorType *ot)
05246 {
05247         /* identifiers */
05248         ot->name= "Sample Color";
05249         ot->idname= "PAINT_OT_sample_color";
05250         
05251         /* api callbacks */
05252         ot->exec= sample_color_exec;
05253         ot->invoke= sample_color_invoke;
05254         ot->modal= sample_color_modal;
05255         ot->poll= image_paint_sample_color_poll;
05256 
05257         /* flags */
05258         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05259 
05260         /* properties */
05261         RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates.", 0, 16384);
05262 }
05263 
05264 /******************** set clone cursor operator ********************/
05265 
05266 static int set_clone_cursor_exec(bContext *C, wmOperator *op)
05267 {
05268         Scene *scene= CTX_data_scene(C);
05269         View3D *v3d= CTX_wm_view3d(C);
05270         float *cursor= give_cursor(scene, v3d);
05271 
05272         RNA_float_get_array(op->ptr, "location", cursor);
05273         
05274         ED_area_tag_redraw(CTX_wm_area(C));
05275         
05276         return OPERATOR_FINISHED;
05277 }
05278 
05279 static int set_clone_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event)
05280 {
05281         Scene *scene= CTX_data_scene(C);
05282         View3D *v3d= CTX_wm_view3d(C);
05283         ARegion *ar= CTX_wm_region(C);
05284         float location[3];
05285 
05286         view3d_operator_needs_opengl(C);
05287 
05288         if(!ED_view3d_autodist(scene, ar, v3d, event->mval, location))
05289                 return OPERATOR_CANCELLED;
05290 
05291         RNA_float_set_array(op->ptr, "location", location);
05292 
05293         return set_clone_cursor_exec(C, op);
05294 }
05295 
05296 void PAINT_OT_clone_cursor_set(wmOperatorType *ot)
05297 {
05298         /* identifiers */
05299         ot->name= "Set Clone Cursor";
05300         ot->idname= "PAINT_OT_clone_cursor_set";
05301         
05302         /* api callbacks */
05303         ot->exec= set_clone_cursor_exec;
05304         ot->invoke= set_clone_cursor_invoke;
05305         ot->poll= image_paint_3d_poll;
05306 
05307         /* flags */
05308         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05309 
05310         /* properties */
05311         RNA_def_float_vector(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in world space coordinates.", -10000.0f, 10000.0f);
05312 }
05313 
05314 /******************** texture paint toggle operator ********************/
05315 
05316 static int texture_paint_toggle_poll(bContext *C)
05317 {
05318         if(CTX_data_edit_object(C))
05319                 return 0;
05320         if(CTX_data_active_object(C)==NULL)
05321                 return 0;
05322 
05323         return 1;
05324 }
05325 
05326 static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
05327 {
05328         Scene *scene= CTX_data_scene(C);
05329         Object *ob= CTX_data_active_object(C);
05330         Mesh *me= NULL;
05331         
05332         if(ob==NULL)
05333                 return OPERATOR_CANCELLED;
05334         
05335         if (object_data_is_libdata(ob)) {
05336                 BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata.");
05337                 return OPERATOR_CANCELLED;
05338         }
05339 
05340         me= get_mesh(ob);
05341 
05342         if(!(ob->mode & OB_MODE_TEXTURE_PAINT) && !me) {
05343                 BKE_report(op->reports, RPT_ERROR, "Can only enter texture paint mode for mesh objects.");
05344                 return OPERATOR_CANCELLED;
05345         }
05346 
05347         if(ob->mode & OB_MODE_TEXTURE_PAINT) {
05348                 ob->mode &= ~OB_MODE_TEXTURE_PAINT;
05349 
05350                 if(U.glreslimit != 0)
05351                         GPU_free_images();
05352                 GPU_paint_set_mipmap(1);
05353 
05354                 toggle_paint_cursor(C, 0);
05355         }
05356         else {
05357                 ob->mode |= OB_MODE_TEXTURE_PAINT;
05358 
05359                 if(me->mtface==NULL)
05360                         me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
05361                                                          NULL, me->totface);
05362 
05363                 paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
05364 
05365                 if(U.glreslimit != 0)
05366                         GPU_free_images();
05367                 GPU_paint_set_mipmap(0);
05368 
05369                 toggle_paint_cursor(C, 1);
05370         }
05371 
05372         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
05373         WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
05374 
05375         return OPERATOR_FINISHED;
05376 }
05377 
05378 void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
05379 {
05380         /* identifiers */
05381         ot->name= "Texture Paint Toggle";
05382         ot->idname= "PAINT_OT_texture_paint_toggle";
05383         
05384         /* api callbacks */
05385         ot->exec= texture_paint_toggle_exec;
05386         ot->poll= texture_paint_toggle_poll;
05387 
05388         /* flags */
05389         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05390 }
05391 
05392 static int texture_paint_poll(bContext *C)
05393 {
05394         if(texture_paint_toggle_poll(C))
05395                 if(CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT)
05396                         return 1;
05397         
05398         return 0;
05399 }
05400 
05401 int image_texture_paint_poll(bContext *C)
05402 {
05403         return (texture_paint_poll(C) || image_paint_poll(C));
05404 }
05405 
05406 int facemask_paint_poll(bContext *C)
05407 {
05408         return paint_facesel_test(CTX_data_active_object(C));
05409 }
05410 
05411 /* use project paint to re-apply an image */
05412 static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
05413 {
05414         Image *image= BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image"));
05415         Scene *scene= CTX_data_scene(C);
05416         ProjPaintState ps= {NULL};
05417         int orig_brush_size;
05418         IDProperty *idgroup;
05419         IDProperty *view_data= NULL;
05420 
05421         project_state_init(C, OBACT, &ps);
05422 
05423         if(ps.ob==NULL || ps.ob->type != OB_MESH) {
05424                 BKE_report(op->reports, RPT_ERROR, "No active mesh object.");
05425                 return OPERATOR_CANCELLED;
05426         }
05427 
05428         if(image==NULL) {
05429                 BKE_report(op->reports, RPT_ERROR, "Image could not be found.");
05430                 return OPERATOR_CANCELLED;
05431         }
05432 
05433         ps.reproject_image= image;
05434         ps.reproject_ibuf= BKE_image_get_ibuf(image, NULL);
05435 
05436         if(ps.reproject_ibuf==NULL || ps.reproject_ibuf->rect==NULL) {
05437                 BKE_report(op->reports, RPT_ERROR, "Image data could not be found.");
05438                 return OPERATOR_CANCELLED;
05439         }
05440 
05441         idgroup= IDP_GetProperties(&image->id, 0);
05442 
05443         if(idgroup) {
05444                 view_data= IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY);
05445 
05446                 /* type check to make sure its ok */
05447                 if(view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) {
05448                         BKE_report(op->reports, RPT_ERROR, "Image project data invalid.");
05449                         return OPERATOR_CANCELLED;
05450                 }
05451         }
05452 
05453         if(view_data) {
05454                 /* image has stored view projection info */
05455                 ps.source= PROJ_SRC_IMAGE_VIEW;
05456         }
05457         else {
05458                 ps.source= PROJ_SRC_IMAGE_CAM;
05459 
05460                 if(scene->camera==NULL) {
05461                         BKE_report(op->reports, RPT_ERROR, "No active camera set.");
05462                         return OPERATOR_CANCELLED;
05463                 }
05464         }
05465 
05466         /* override */
05467         ps.is_texbrush= 0;
05468         ps.is_airbrush= 1;
05469         orig_brush_size= brush_size(ps.brush);
05470         brush_set_size(ps.brush, 32); /* cover the whole image */
05471 
05472         ps.tool= PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */
05473 
05474         scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
05475 
05476         undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
05477                 image_undo_restore, image_undo_free);
05478 
05479         /* allocate and initialize spacial data structures */
05480         project_paint_begin(&ps);
05481 
05482         if(ps.dm==NULL) {
05483                 brush_set_size(ps.brush, orig_brush_size);
05484                 return OPERATOR_CANCELLED;
05485         }
05486         else {
05487                 float pos[2]= {0.0, 0.0};
05488                 float lastpos[2]= {0.0, 0.0};
05489                 int a;
05490 
05491                 for (a=0; a < ps.image_tot; a++)
05492                         partial_redraw_array_init(ps.projImages[a].partRedrawRect);
05493 
05494                 project_paint_op(&ps, NULL, lastpos, pos);
05495 
05496                 project_image_refresh_tagged(&ps);
05497 
05498                 for (a=0; a < ps.image_tot; a++) {
05499                         GPU_free_image(ps.projImages[a].ima);
05500                         WM_event_add_notifier(C, NC_IMAGE|NA_EDITED, ps.projImages[a].ima);
05501                 }
05502         }
05503 
05504         project_paint_end(&ps);
05505 
05506         scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
05507         brush_set_size(ps.brush, orig_brush_size);
05508 
05509         return OPERATOR_FINISHED;
05510 }
05511 
05512 void PAINT_OT_project_image(wmOperatorType *ot)
05513 {
05514         PropertyRNA *prop;
05515 
05516         /* identifiers */
05517         ot->name= "Project Image";
05518         ot->idname= "PAINT_OT_project_image";
05519         ot->description= "Project an edited render from the active camera back onto the object";
05520 
05521         /* api callbacks */
05522         ot->invoke= WM_enum_search_invoke;
05523         ot->exec= texture_paint_camera_project_exec;
05524 
05525         /* flags */
05526         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
05527 
05528         prop= RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", "");
05529         RNA_def_enum_funcs(prop, RNA_image_itemf);
05530         ot->prop= prop;
05531 }
05532 
05533 static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
05534 {
05535         Image *image;
05536         ImBuf *ibuf;
05537         char filename[FILE_MAX];
05538 
05539         Scene *scene= CTX_data_scene(C);
05540         ToolSettings *settings= scene->toolsettings;
05541         int w= settings->imapaint.screen_grab_size[0];
05542         int h= settings->imapaint.screen_grab_size[1];
05543         int maxsize;
05544         char err_out[256]= "unknown";
05545 
05546         RNA_string_get(op->ptr, "filepath", filename);
05547 
05548         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
05549 
05550         if(w > maxsize) w= maxsize;
05551         if(h > maxsize) h= maxsize;
05552 
05553         ibuf= ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, err_out);
05554         if(!ibuf) {
05555                 /* Mostly happens when OpenGL offscreen buffer was failed to create, */
05556                 /* but could be other reasons. Should be handled in the future. nazgul */
05557                 BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer: %s", err_out);
05558                 return OPERATOR_CANCELLED;
05559         }
05560 
05561         image= BKE_add_image_imbuf(ibuf);
05562 
05563         if(image) {
05564                 /* now for the trickyness. store the view projection here!
05565                  * reprojection will reuse this */
05566                 View3D *v3d= CTX_wm_view3d(C);
05567                 RegionView3D *rv3d= CTX_wm_region_view3d(C);
05568 
05569                 IDPropertyTemplate val;
05570                 IDProperty *idgroup= IDP_GetProperties(&image->id, 1);
05571                 IDProperty *view_data;
05572                 int orth;
05573                 float *array;
05574 
05575                 val.array.len = PROJ_VIEW_DATA_SIZE;
05576                 val.array.type = IDP_FLOAT;
05577                 view_data = IDP_New(IDP_ARRAY, val, PROJ_VIEW_DATA_ID);
05578 
05579                 array= (float *)IDP_Array(view_data);
05580                 memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat)/sizeof(float);
05581                 memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat)/sizeof(float);
05582                 orth= project_paint_view_clip(v3d, rv3d, &array[0], &array[1]);
05583                 array[2]= orth ? 1.0f : 0.0f; /* using float for a bool is dodgy but since its an extra member in the array... easier then adding a single bool prop */
05584 
05585                 IDP_AddToGroup(idgroup, view_data);
05586 
05587                 rename_id(&image->id, "image_view");
05588         }
05589 
05590         return OPERATOR_FINISHED;
05591 }
05592 
05593 void PAINT_OT_image_from_view(wmOperatorType *ot)
05594 {
05595         /* identifiers */
05596         ot->name= "Image from View";
05597         ot->idname= "PAINT_OT_image_from_view";
05598         ot->description= "Make an image from the current 3D view for re-projection";
05599 
05600         /* api callbacks */
05601         ot->exec= texture_paint_image_from_view_exec;
05602         ot->poll= ED_operator_region_view3d_active;
05603 
05604         /* flags */
05605         ot->flag= OPTYPE_REGISTER;
05606 
05607         RNA_def_string_file_name(ot->srna, "filepath", "", FILE_MAX, "File Path", "Name of the file");
05608 }