Bugfix: texture paint didn't work correct with modifiers.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 12 Sep 2006 16:53:27 +0000 (16:53 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 12 Sep 2006 16:53:27 +0000 (16:53 +0000)
source/blender/blenkernel/intern/brush.c
source/blender/src/editface.c
source/blender/src/imagepaint.c

index 6abe66be36b06a4e938f329ec05ae2720ae14887..5ade66e456658191097b32fc5c4445ecf3de7775 100644 (file)
@@ -472,6 +472,11 @@ struct BrushPainter {
 
        short firsttouch;               /* first paint op */
 
+       float startsize;
+       float startalpha;
+       float startinnerradius;
+       float startspacing;
+
        BrushPainterCache cache;
 };
 
@@ -483,6 +488,11 @@ BrushPainter *brush_painter_new(Brush *brush)
        painter->firsttouch= 1;
        painter->cache.lastsize= -1; /* force ibuf create in refresh */
 
+       painter->startsize = brush->size;
+       painter->startalpha = brush->alpha;
+       painter->startinnerradius = brush->innerradius;
+       painter->startspacing = brush->spacing;
+
        return painter;
 }
 
@@ -510,6 +520,13 @@ void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly
 
 void brush_painter_free(BrushPainter *painter)
 {
+       Brush *brush = painter->brush;
+
+       brush->size = painter->startsize;
+       brush->alpha = painter->startalpha;
+       brush->innerradius = painter->startinnerradius;
+       brush->spacing = painter->startspacing;
+
        if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf);
        if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf);
        if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf);
@@ -757,9 +774,10 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
 #endif
        else {
                float startdistance, spacing, step, paintpos[2], dmousepos[2];
+               float brushsize = MAX2(1.0, brush->size);
 
                /* compute brush spacing adapted to brush size */
-               spacing= brush->size*brush->spacing*0.01f;
+               spacing= brushsize*brush->spacing*0.01f;
 
                /* setup starting distance, direction vector and accumulated distance */
                startdistance= painter->accumdistance;
index fb452c2723c3bb7081f535aaae1a6c346ac0c3a6..71ed5a4516ba6b5c943f0a8168167a3d43a0c91c 100644 (file)
@@ -56,7 +56,9 @@
 #include "DNA_view3d_types.h"
 
 #include "BKE_brush.h"
+#include "BKE_customdata.h"
 #include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_mesh.h"
@@ -1535,9 +1537,8 @@ static void texpaint_project(Object *ob, double *model, double *proj, GLint *vie
        pco[1]= (float)winy;
 }
 
-static int texpaint_projected_verts(Object *ob, Mesh *mesh, TFace *tf, float *v1, float *v2, float *v3, float *v4)
+static int texpaint_projected_verts(Object *ob, MFace *mf, TFace *tf, MVert *mv, float *v1, float *v2, float *v3, float *v4)
 {
-       MFace *mf = mesh->mface + (tf - mesh->tface);
        double model[16], proj[16];
        GLint view[4];
 
@@ -1550,53 +1551,85 @@ static int texpaint_projected_verts(Object *ob, Mesh *mesh, TFace *tf, float *v1
        view[0] = view[1] = 0;
 
        /* project the verts */
-       texpaint_project(ob, model, proj, view, (mesh->mvert+mf->v1)->co, v1);
-       texpaint_project(ob, model, proj, view, (mesh->mvert+mf->v2)->co, v2);
-       texpaint_project(ob, model, proj, view, (mesh->mvert+mf->v3)->co, v3);
+       texpaint_project(ob, model, proj, view, mv[0].co, v1);
+       texpaint_project(ob, model, proj, view, mv[1].co, v2);
+       texpaint_project(ob, model, proj, view, mv[2].co, v3);
        if(mf->v4)
-               texpaint_project(ob, model, proj, view, (mesh->mvert+mf->v4)->co, v4);
+               texpaint_project(ob, model, proj, view, mv[3].co, v4);
 
        return (mf->v4? 4: 3);
 }
 
 /* compute uv coordinates of mouse in face */
-void texpaint_pick_uv(Object *ob, Mesh *mesh, TFace *tf, short *xy, float *uv)
+void texpaint_pick_uv(Object *ob, Mesh *mesh, unsigned int faceindex, short *xy, float *uv)
 {
-       float v1[2], v2[2], v3[2], v4[2], p[2], w[3], w2[3];
-       float absw, absw2;
-       int nvert;
-
-       /* compute barycentric coordinates of point in face and interpolate uv's.
-          it's ok to compute the barycentric coords on the projected positions,
-          because they are invariant under affine transform */
-       nvert= texpaint_projected_verts(ob, mesh, tf, v1, v2, v3, v4);
-
-       p[0]= xy[0];
-       p[1]= xy[1];
-
-       if (nvert == 4) {
-               texpaint_barycentric_2d(v1, v2, v4, p, w);
-               texpaint_barycentric_2d(v2, v3, v4, p, w2);
-
-               /* the triangle with the largest absolute values is the one with the
-                  most negative weights */
-               absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
-               absw2= fabs(w2[0]) + fabs(w2[1]) + fabs(w2[2]);
-               
-               if(absw > absw2) {
-                       uv[0]= tf->uv[1][0]*w2[0] + tf->uv[2][0]*w2[1] + tf->uv[3][0]*w2[2];
-                       uv[1]= tf->uv[1][1]*w2[0] + tf->uv[2][1]*w2[1] + tf->uv[3][1]*w2[2];
-               }
-               else {
-                       uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2];
-                       uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2];
+       float v1[2], v2[2], v3[2], v4[2], p[2], w[3];
+       float absw, minabsw;
+       int nvert, dmNeedsFree;
+       DerivedMesh *dm = mesh_get_derived_final(ob, &dmNeedsFree);
+       int *index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
+       TFace *tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE), *tf;
+       int numfaces = dm->getNumFaces(dm), a;
+       MFace mf;
+       MVert mv[4];
+
+       minabsw = 1e10;
+       uv[0] = uv[1] = 0.0;
+
+       /* test all faces in the derivedmesh with the original index of the picked face */
+       for (a = 0; a < numfaces; a++) {
+               if (index[a] == faceindex) {
+                       dm->getFace(dm, a, &mf);
+
+                       dm->getVert(dm, mf.v1, &mv[0]);
+                       dm->getVert(dm, mf.v2, &mv[1]);
+                       dm->getVert(dm, mf.v3, &mv[2]);
+                       if (mf.v4)
+                               dm->getVert(dm, mf.v4, &mv[3]);
+
+                       tf= &tface[a];
+
+                       /* compute barycentric coordinates of point in face and interpolate uv's.
+                          it's ok to compute the barycentric coords on the projected positions,
+                          because they are invariant under affine transform */
+                       nvert= texpaint_projected_verts(ob, &mf, tf, mv, v1, v2, v3, v4);
+
+                       p[0]= xy[0];
+                       p[1]= xy[1];
+
+                       if (nvert == 4) {
+                               /* the triangle with the largest absolute values is the one with the
+                                  most negative weights */
+                               texpaint_barycentric_2d(v1, v2, v4, p, w);
+                               absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
+                               if(absw < minabsw) {
+                                       uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[3][0]*w[2];
+                                       uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[3][1]*w[2];
+                                       minabsw = absw;
+                               }
+
+                               texpaint_barycentric_2d(v2, v3, v4, p, w);
+                               absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
+                               if (absw < minabsw) {
+                                       uv[0]= tf->uv[1][0]*w[0] + tf->uv[2][0]*w[1] + tf->uv[3][0]*w[2];
+                                       uv[1]= tf->uv[1][1]*w[0] + tf->uv[2][1]*w[1] + tf->uv[3][1]*w[2];
+                                       minabsw = absw;
+                               }
+                       }
+                       else {
+                               texpaint_barycentric_2d(v1, v2, v3, p, w);
+                               absw= fabs(w[0]) + fabs(w[1]) + fabs(w[2]);
+                               if (absw < minabsw) {
+                                       uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2];
+                                       uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2];
+                                       minabsw = absw;
+                               }
+                       }
                }
        }
-       else {
-               texpaint_barycentric_2d(v1, v2, v3, p, w);
-               uv[0]= tf->uv[0][0]*w[0] + tf->uv[1][0]*w[1] + tf->uv[2][0]*w[2];
-               uv[1]= tf->uv[0][1]*w[0] + tf->uv[1][1]*w[1] + tf->uv[2][1]*w[2];
-       }
+
+       if (dmNeedsFree)
+               dm->release(dm);
 }
 
  /* Selects all faces which have the same uv-texture as the active face 
index d97f63b8bc17946e0bdcb8a332242da11a61d32a..dc7db64836ad3e8137bece1d860187eb84f50169 100644 (file)
@@ -112,7 +112,7 @@ typedef struct ImagePaintState {
        /* texture paint only */
        Object *ob;
        Mesh *me;
-       TFace *tface;
+       int faceindex;
        float uv[2];
 } ImagePaintState;
 
@@ -459,7 +459,7 @@ static void imapaint_compute_uvco(short *mval, float *uv)
 /* 3D TexturePaint */
 
 int facesel_face_pick(Mesh *me, short *mval, unsigned int *index, short rect);
-void texpaint_pick_uv(Object *ob, Mesh *mesh, TFace *tf, short *xy, float *mousepos);
+void texpaint_pick_uv(Object *ob, Mesh *mesh, unsigned int faceindex, short *xy, float *mousepos);
 
 static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float *uv)
 {
@@ -536,19 +536,17 @@ static int imapaint_do_paint(ImagePaintState *s, BrushPainter *painter, Image *i
 
 static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpaint, short *prevmval, short *mval, double time)
 {
-       TFace *newtface = NULL;
        Image *newimage = NULL;
        float fwuv[2], bkuv[2], newuv[2];
-       unsigned int face_index;
+       unsigned int newfaceindex;
        int breakstroke = 0, redraw = 0;
 
        if (texpaint) {
 
                /* pick face and image */
-               if (facesel_face_pick(s->me, mval, &face_index, 0)) {
-                       newtface = s->me->tface + face_index;
-                       newimage = (Image*)newtface->tpage;
-                       texpaint_pick_uv(s->ob, s->me, newtface, mval, newuv);
+               if (facesel_face_pick(s->me, mval, &newfaceindex, 0)) {
+                       newimage = (Image*)((s->me->tface+newfaceindex)->tpage);
+                       texpaint_pick_uv(s->ob, s->me, newfaceindex, mval, newuv);
                }
                else
                        newuv[0] = newuv[1] = 0.0f;
@@ -556,8 +554,8 @@ static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpain
                /* see if stroke is broken, and if so finish painting in old position */
                if (s->image) {
                        if (newimage == s->image) {
-                               texpaint_pick_uv(s->ob, s->me, s->tface, mval, fwuv);
-                               texpaint_pick_uv(s->ob, s->me, newtface, prevmval, bkuv);
+                               texpaint_pick_uv(s->ob, s->me, s->faceindex, mval, fwuv);
+                               texpaint_pick_uv(s->ob, s->me, newfaceindex, prevmval, bkuv);
                                breakstroke= texpaint_break_stroke(s->uv, fwuv, bkuv, newuv);
                        }
                        else
@@ -565,7 +563,7 @@ static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpain
                }
 
                if (breakstroke) {
-                       texpaint_pick_uv(s->ob, s->me, s->tface, mval, fwuv);
+                       texpaint_pick_uv(s->ob, s->me, s->faceindex, mval, fwuv);
                        redraw |= imapaint_do_paint(s, painter, s->image, texpaint, fwuv, time, 1);
                        imapaint_clear_partial_redraw();
                        brush_painter_break_stroke(painter);
@@ -585,7 +583,7 @@ static void imapaint_do(ImagePaintState *s, BrushPainter *painter, short texpain
 
                /* update state */
                s->image = newimage;
-               s->tface = newtface;
+               s->faceindex = newfaceindex;
                s->uv[0] = newuv[0];
                s->uv[1] = newuv[1];
        }
@@ -649,6 +647,8 @@ void imagepaint_paint(short mousebutton, short texpaint)
 
        imapaint_do(&s, painter, texpaint, prevmval, mval, time);
 
+       //get_tablet_data();
+
        /* paint loop */
        while(get_mbut() & mousebutton) {
                getmouseco_areawin(mval);
@@ -658,6 +658,7 @@ void imagepaint_paint(short mousebutton, short texpaint)
                        imapaint_do(&s, painter, texpaint, prevmval, mval, time);
                        prevmval[0]= mval[0];
                        prevmval[1]= mval[1];
+                       //s.brush->size = MAX2(1, MIN2(200, s.brush->size*0.9));
                }
                else if (s.brush->flag & BRUSH_AIRBRUSH)
                        imapaint_do(&s, painter, texpaint, prevmval, mval, time);