Blender V2.61 - r43446

paint_image.c

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