svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / src / vpaint.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 #ifdef WIN32
34 #include <io.h>
35 #else
36 #include <unistd.h>
37 #endif   
38
39 #include "MEM_guardedalloc.h"
40
41 #include "IMB_imbuf.h"
42 #include "IMB_imbuf_types.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_arithb.h"
46 #include "MTC_matrixops.h"
47
48 #include "DNA_action_types.h"
49 #include "DNA_armature_types.h"
50 #include "DNA_brush_types.h"
51 #include "DNA_cloth_types.h"
52 #include "DNA_mesh_types.h"
53 #include "DNA_meshdata_types.h"
54 #include "DNA_modifier_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_object_force.h"
57 #include "DNA_particle_types.h"
58 #include "DNA_screen_types.h"
59 #include "DNA_space_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_view3d_types.h"
62 #include "DNA_userdef_types.h"
63
64 #include "BKE_armature.h"
65 #include "BKE_DerivedMesh.h"
66 #include "BKE_cloth.h"
67 #include "BKE_customdata.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_deform.h"
70 #include "BKE_displist.h"
71 #include "BKE_global.h"
72 #include "BKE_mesh.h"
73 #include "BKE_modifier.h"
74 #include "BKE_multires.h"
75 #include "BKE_object.h"
76 #include "BKE_utildefines.h"
77
78 #include "BIF_editview.h"
79 #include "BIF_graphics.h"
80 #include "BIF_glutil.h"
81 #include "BIF_gl.h"
82 #include "BIF_interface.h"
83 #include "BIF_meshtools.h"
84 #include "BIF_mywindow.h"
85 #include "BIF_space.h"
86 #include "BIF_screen.h"
87 #include "BIF_toolbox.h"
88
89 #include "BDR_vpaint.h"
90 #include "BDR_editobject.h"
91
92 #include "BSE_drawview.h"
93 #include "BSE_trans_types.h"
94 #include "BSE_view.h"
95
96 #include "multires.h"
97 #include "mydevice.h"
98 #include "blendef.h"
99
100 #include "BIF_editdeform.h"
101
102         /* Gvp.mode */
103 #define VP_MIX  0
104 #define VP_ADD  1
105 #define VP_SUB  2
106 #define VP_MUL  3
107 #define VP_BLUR 4
108 #define VP_LIGHTEN      5
109 #define VP_DARKEN       6
110
111 #define MAXINDEX        512000
112
113 VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT+VP_SPRAY, 0};
114 VPaint Gwp= {1.0, 1.0, 1.0, 1.0, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT, 0};
115
116 static int *get_indexarray(void)
117 {
118         return MEM_mallocN(sizeof(int)*MAXINDEX + 2, "vertexpaint");
119 }
120
121 void free_vertexpaint()
122 {
123         
124         if(Gvp.vpaint_prev) MEM_freeN(Gvp.vpaint_prev);
125         Gvp.vpaint_prev= NULL;
126         
127         mesh_octree_table(NULL, NULL, 'e');
128 }
129
130 /* in contradiction to cpack drawing colors, the MCOL colors (vpaint colors) are per byte! 
131    so not endian sensitive. Mcol = ABGR!!! so be cautious with cpack calls */
132
133 unsigned int rgba_to_mcol(float r, float g, float b, float a)
134 {
135         int ir, ig, ib, ia;
136         unsigned int col;
137         char *cp;
138         
139         ir= floor(255.0*r);
140         if(ir<0) ir= 0; else if(ir>255) ir= 255;
141         ig= floor(255.0*g);
142         if(ig<0) ig= 0; else if(ig>255) ig= 255;
143         ib= floor(255.0*b);
144         if(ib<0) ib= 0; else if(ib>255) ib= 255;
145         ia= floor(255.0*a);
146         if(ia<0) ia= 0; else if(ia>255) ia= 255;
147         
148         cp= (char *)&col;
149         cp[0]= ia;
150         cp[1]= ib;
151         cp[2]= ig;
152         cp[3]= ir;
153         
154         return col;
155         
156 }
157
158 static unsigned int vpaint_get_current_col(VPaint *vp)
159 {
160         return rgba_to_mcol(vp->r, vp->g, vp->b, 1.0f);
161 }
162
163 void do_shared_vertexcol(Mesh *me)
164 {
165         /* if no mcol: do not do */
166         /* if tface: only the involved faces, otherwise all */
167         MFace *mface;
168         MTFace *tface;
169         int a;
170         short *scolmain, *scol;
171         char *mcol;
172         
173         if(me->mcol==0 || me->totvert==0 || me->totface==0) return;
174         
175         scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain");
176         
177         tface= me->mtface;
178         mface= me->mface;
179         mcol= (char *)me->mcol;
180         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
181                 if((tface && tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
182                         scol= scolmain+4*mface->v1;
183                         scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3];
184                         scol= scolmain+4*mface->v2;
185                         scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7];
186                         scol= scolmain+4*mface->v3;
187                         scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11];
188                         if(mface->v4) {
189                                 scol= scolmain+4*mface->v4;
190                                 scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15];
191                         }
192                 }
193                 if(tface) tface++;
194         }
195         
196         a= me->totvert;
197         scol= scolmain;
198         while(a--) {
199                 if(scol[0]>1) {
200                         scol[1]/= scol[0];
201                         scol[2]/= scol[0];
202                         scol[3]/= scol[0];
203                 }
204                 scol+= 4;
205         }
206         
207         tface= me->mtface;
208         mface= me->mface;
209         mcol= (char *)me->mcol;
210         for(a=me->totface; a>0; a--, mface++, mcol+=16) {
211                 if((tface && tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) {
212                         scol= scolmain+4*mface->v1;
213                         mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3];
214                         scol= scolmain+4*mface->v2;
215                         mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3];
216                         scol= scolmain+4*mface->v3;
217                         mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3];
218                         if(mface->v4) {
219                                 scol= scolmain+4*mface->v4;
220                                 mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3];
221                         }
222                 }
223                 if(tface) tface++;
224         }
225
226         MEM_freeN(scolmain);
227 }
228
229 void make_vertexcol(int shade)  /* single ob */
230 {
231         Object *ob;
232         Mesh *me;
233
234         if(G.obedit) {
235                 error("Unable to perform function in Edit Mode");
236                 return;
237         }
238         
239         ob= OBACT;
240         if(!ob || ob->id.lib) return;
241         me= get_mesh(ob);
242         if(me==0) return;
243
244         /* copies from shadedisplist to mcol */
245         if(!me->mcol) {
246                 CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
247                 mesh_update_customdata_pointers(me);
248         }
249
250         if(shade)
251                 shadeMeshMCol(ob, me);
252         else
253                 memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
254         
255         if (me->mr) multires_load_cols(me);
256         
257         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
258         
259         allqueue(REDRAWBUTSEDIT, 0);
260         allqueue(REDRAWVIEW3D, 0);
261 }
262
263 static void copy_vpaint_prev(VPaint *vp, unsigned int *mcol, int tot)
264 {
265         if(vp->vpaint_prev) {
266                 MEM_freeN(vp->vpaint_prev);
267                 vp->vpaint_prev= NULL;
268         }
269         vp->tot= tot;   
270         
271         if(mcol==NULL || tot==0) return;
272         
273         vp->vpaint_prev= MEM_mallocN(4*sizeof(int)*tot, "vpaint_prev");
274         memcpy(vp->vpaint_prev, mcol, 4*sizeof(int)*tot);
275         
276 }
277
278 static void copy_wpaint_prev (VPaint *vp, MDeformVert *dverts, int dcount)
279 {
280         if (vp->wpaint_prev) {
281                 free_dverts(vp->wpaint_prev, vp->tot);
282                 vp->wpaint_prev= NULL;
283         }
284         
285         if(dverts && dcount) {
286                 
287                 vp->wpaint_prev = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaint prev");
288                 vp->tot = dcount;
289                 copy_dverts (vp->wpaint_prev, dverts, dcount);
290         }
291 }
292
293
294 void clear_vpaint()
295 {
296         Mesh *me;
297         Object *ob;
298         unsigned int *to, paintcol;
299         int a;
300         
301         if((G.f & G_VERTEXPAINT)==0) return;
302
303         ob= OBACT;
304         me= get_mesh(ob);
305         if(!ob || ob->id.lib) return;
306
307         if(me==0 || me->mcol==0 || me->totface==0) return;
308
309         paintcol= vpaint_get_current_col(&Gvp);
310
311         to= (unsigned int *)me->mcol;
312         a= 4*me->totface;
313         while(a--) {
314                 *to= paintcol;
315                 to++; 
316         }
317         BIF_undo_push("Clear vertex colors");
318         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
319         
320         allqueue(REDRAWVIEW3D, 0);
321 }
322
323 void clear_vpaint_selectedfaces()
324 {
325         Mesh *me;
326         MFace *mf;
327         Object *ob;
328         unsigned int paintcol, *mcol;
329         int i;
330
331         ob= OBACT;
332         me= get_mesh(ob);
333         if(me==0 || me->totface==0) return;
334
335         if(!me->mcol)
336                 make_vertexcol(0);
337
338         paintcol= vpaint_get_current_col(&Gvp);
339
340         mf = me->mface;
341         mcol = (unsigned int*)me->mcol;
342         for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
343                 if (mf->flag & ME_FACE_SEL) {
344                         mcol[0] = paintcol;
345                         mcol[1] = paintcol;
346                         mcol[2] = paintcol;
347                         mcol[3] = paintcol;
348                 }
349         }
350         
351         BIF_undo_push("Clear vertex colors");
352         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
353         allqueue(REDRAWVIEW3D, 0);
354 }
355
356
357 /* fills in the selected faces with the current weight and vertex group */
358 void clear_wpaint_selectedfaces()
359 {
360         extern float editbutvweight;
361         float paintweight= editbutvweight;
362         Mesh *me;
363         MFace *mface;
364         Object *ob;
365         MDeformWeight *dw, *uw;
366         int *indexar;
367         int index, vgroup;
368         unsigned int faceverts[5]={0,0,0,0,0};
369         unsigned char i;
370         int vgroup_mirror= -1;
371         
372         ob= OBACT;
373         me= ob->data;
374         if(me==0 || me->totface==0 || me->dvert==0 || !me->mface) return;
375         
376         indexar= get_indexarray();
377         for(index=0, mface=me->mface; index<me->totface; index++, mface++) {
378                 if((mface->flag & ME_FACE_SEL)==0)
379                         indexar[index]= 0;
380                 else
381                         indexar[index]= index+1;
382         }
383         
384         vgroup= ob->actdef-1;
385         
386         /* directly copied from weight_paint, should probaby split into a seperate function */
387         /* if mirror painting, find the other group */          
388         if(Gwp.flag & VP_MIRROR_X) {
389                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
390                 if(defgroup) {
391                         bDeformGroup *curdef;
392                         int actdef= 0;
393                         char name[32];
394
395                         BLI_strncpy(name, defgroup->name, 32);
396                         bone_flip_name(name, 0);                /* 0 = don't strip off number extensions */
397                         
398                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
399                                 if (!strcmp(curdef->name, name))
400                                         break;
401                         if(curdef==NULL) {
402                                 int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
403                                 curdef= add_defgroup_name (ob, name);
404                                 ob->actdef= olddef;
405                         }
406                         
407                         if(curdef && curdef!=defgroup)
408                                 vgroup_mirror= actdef;
409                 }
410         }
411         /* end copy from weight_paint*/
412         
413         copy_wpaint_prev(&Gwp, me->dvert, me->totvert);
414         
415         for(index=0; index<me->totface; index++) {
416                 if(indexar[index] && indexar[index]<=me->totface) {
417                         mface= me->mface + (indexar[index]-1);
418                         /* just so we can loop through the verts */
419                         faceverts[0]= mface->v1;
420                         faceverts[1]= mface->v2;
421                         faceverts[2]= mface->v3;
422                         faceverts[3]= mface->v4;
423                         for (i=0; i<3 || faceverts[i]; i++) {
424                                 if(!((me->dvert+faceverts[i])->flag)) {
425                                         dw= verify_defweight(me->dvert+faceverts[i], vgroup);
426                                         if(dw) {
427                                                 uw= verify_defweight(Gwp.wpaint_prev+faceverts[i], vgroup);
428                                                 uw->weight= dw->weight; /* set the undio weight */
429                                                 dw->weight= paintweight;
430                                                 
431                                                 if(Gwp.flag & VP_MIRROR_X) {    /* x mirror painting */
432                                                         int j= mesh_get_x_mirror_vert(ob, faceverts[i]);
433                                                         if(j>=0) {
434                                                                 /* copy, not paint again */
435                                                                 if(vgroup_mirror != -1) {
436                                                                         dw= verify_defweight(me->dvert+j, vgroup_mirror);
437                                                                         uw= verify_defweight(Gwp.wpaint_prev+j, vgroup_mirror);
438                                                                 } else {
439                                                                         dw= verify_defweight(me->dvert+j, vgroup);
440                                                                         uw= verify_defweight(Gwp.wpaint_prev+j, vgroup);
441                                                                 }
442                                                                 uw->weight= dw->weight; /* set the undo weight */
443                                                                 dw->weight= paintweight;
444                                                         }
445                                                 }
446                                         }
447                                         (me->dvert+faceverts[i])->flag= 1;
448                                 }
449                         }
450                 }
451         }
452         
453         index=0;
454         while (index<me->totvert) {
455                 (me->dvert+index)->flag= 0;
456                 index++;
457         }
458         
459         MEM_freeN(indexar);
460         copy_wpaint_prev(&Gwp, NULL, 0);
461
462         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
463         BIF_undo_push("Set vertex weight");
464         allqueue(REDRAWVIEW3D, 0);
465 }
466
467
468 void vpaint_dogamma()
469 {
470         Mesh *me;
471         Object *ob;
472         float igam, fac;
473         int a, temp;
474         char *cp, gamtab[256];
475
476         if((G.f & G_VERTEXPAINT)==0) return;
477
478         ob= OBACT;
479         me= get_mesh(ob);
480         if(me==0 || me->mcol==0 || me->totface==0) return;
481
482         igam= 1.0/Gvp.gamma;
483         for(a=0; a<256; a++) {
484                 
485                 fac= ((float)a)/255.0;
486                 fac= Gvp.mul*pow( fac, igam);
487                 
488                 temp= 255.9*fac;
489                 
490                 if(temp<=0) gamtab[a]= 0;
491                 else if(temp>=255) gamtab[a]= 255;
492                 else gamtab[a]= temp;
493         }
494
495         a= 4*me->totface;
496         cp= (char *)me->mcol;
497         while(a--) {
498                 
499                 cp[1]= gamtab[ cp[1] ];
500                 cp[2]= gamtab[ cp[2] ];
501                 cp[3]= gamtab[ cp[3] ];
502                 
503                 cp+= 4;
504         }
505         allqueue(REDRAWVIEW3D, 0);
506 }
507
508 /* used for both 3d view and image window */
509 void sample_vpaint()    /* frontbuf */
510 {
511         unsigned int col;
512         int x, y;
513         short mval[2];
514         char *cp;
515         
516         getmouseco_areawin(mval);
517         x= mval[0]; y= mval[1];
518         
519         if(x<0 || y<0) return;
520         if(x>=curarea->winx || y>=curarea->winy) return;
521         
522         x+= curarea->winrct.xmin;
523         y+= curarea->winrct.ymin;
524         
525         glReadBuffer(GL_FRONT);
526         glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
527         glReadBuffer(GL_BACK);
528
529         cp = (char *)&col;
530         
531         if(G.f & (G_VERTEXPAINT|G_WEIGHTPAINT)) {
532                 Gvp.r= cp[0]/255.0f;
533                 Gvp.g= cp[1]/255.0f;
534                 Gvp.b= cp[2]/255.0f;
535         }
536         else {
537                 Brush *brush= G.scene->toolsettings->imapaint.brush;
538
539                 if(brush) {
540                         brush->rgb[0]= cp[0]/255.0f;
541                         brush->rgb[1]= cp[1]/255.0f;
542                         brush->rgb[2]= cp[2]/255.0f;
543
544                         allqueue(REDRAWVIEW3D, 0);
545                         allqueue(REDRAWIMAGE, 0);
546                 }
547         }
548
549         allqueue(REDRAWBUTSEDIT, 0);
550         addqueue(curarea->win, REDRAW, 1); /* needed for when panel is open... */
551 }
552
553 static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac)
554 {
555         char *cp1, *cp2, *cp;
556         int mfac;
557         unsigned int col=0;
558         
559         if(fac==0) return col1;
560         if(fac>=255) return col2;
561
562         mfac= 255-fac;
563         
564         cp1= (char *)&col1;
565         cp2= (char *)&col2;
566         cp=  (char *)&col;
567         
568         cp[0]= 255;
569         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
570         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
571         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
572         
573         return col;
574 }
575
576 static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac)
577 {
578         char *cp1, *cp2, *cp;
579         int temp;
580         unsigned int col=0;
581         
582         if(fac==0) return col1;
583         
584         cp1= (char *)&col1;
585         cp2= (char *)&col2;
586         cp=  (char *)&col;
587         
588         cp[0]= 255;
589         temp= cp1[1] + ((fac*cp2[1])/255);
590         if(temp>254) cp[1]= 255; else cp[1]= temp;
591         temp= cp1[2] + ((fac*cp2[2])/255);
592         if(temp>254) cp[2]= 255; else cp[2]= temp;
593         temp= cp1[3] + ((fac*cp2[3])/255);
594         if(temp>254) cp[3]= 255; else cp[3]= temp;
595         
596         return col;
597 }
598
599 static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac)
600 {
601         char *cp1, *cp2, *cp;
602         int temp;
603         unsigned int col=0;
604         
605         if(fac==0) return col1;
606         
607         cp1= (char *)&col1;
608         cp2= (char *)&col2;
609         cp=  (char *)&col;
610         
611         cp[0]= 255;
612         temp= cp1[1] - ((fac*cp2[1])/255);
613         if(temp<0) cp[1]= 0; else cp[1]= temp;
614         temp= cp1[2] - ((fac*cp2[2])/255);
615         if(temp<0) cp[2]= 0; else cp[2]= temp;
616         temp= cp1[3] - ((fac*cp2[3])/255);
617         if(temp<0) cp[3]= 0; else cp[3]= temp;
618         
619         return col;
620 }
621
622 static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac)
623 {
624         char *cp1, *cp2, *cp;
625         int mfac;
626         unsigned int col=0;
627         
628         if(fac==0) return col1;
629
630         mfac= 255-fac;
631         
632         cp1= (char *)&col1;
633         cp2= (char *)&col2;
634         cp=  (char *)&col;
635         
636         /* first mul, then blend the fac */
637         cp[0]= 255;
638         cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])/255)  )/255;
639         cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])/255)  )/255;
640         cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])/255)  )/255;
641
642         
643         return col;
644 }
645
646 static unsigned int mcol_lighten(unsigned int col1, unsigned int col2, int fac)
647 {
648         char *cp1, *cp2, *cp;
649         int mfac;
650         unsigned int col=0;
651         
652         if(fac==0) return col1;
653         if(fac>=255) return col2;
654
655         mfac= 255-fac;
656         
657         cp1= (char *)&col1;
658         cp2= (char *)&col2;
659         cp=  (char *)&col;
660         
661         /* See if are lighter, if so mix, else dont do anything.
662         if the paint col is darker then the original, then ignore */
663         if (cp1[1]+cp1[2]+cp1[3] > cp2[1]+cp2[2]+cp2[3])
664                 return col1;
665         
666         cp[0]= 255;
667         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
668         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
669         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
670         
671         return col;
672 }
673
674 static unsigned int mcol_darken(unsigned int col1, unsigned int col2, int fac)
675 {
676         char *cp1, *cp2, *cp;
677         int mfac;
678         unsigned int col=0;
679         
680         if(fac==0) return col1;
681         if(fac>=255) return col2;
682
683         mfac= 255-fac;
684         
685         cp1= (char *)&col1;
686         cp2= (char *)&col2;
687         cp=  (char *)&col;
688         
689         /* See if were darker, if so mix, else dont do anything.
690         if the paint col is brighter then the original, then ignore */
691         if (cp1[1]+cp1[2]+cp1[3] < cp2[1]+cp2[2]+cp2[3])
692                 return col1;
693         
694         cp[0]= 255;
695         cp[1]= (mfac*cp1[1]+fac*cp2[1])/255;
696         cp[2]= (mfac*cp1[2]+fac*cp2[2])/255;
697         cp[3]= (mfac*cp1[3]+fac*cp2[3])/255;
698         return col;
699 }
700
701 static void vpaint_blend( unsigned int *col, unsigned int *colorig, unsigned int paintcol, int alpha)
702 {
703
704         if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) *col= mcol_blend( *col, paintcol, alpha);
705         else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha);
706         else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha);
707         else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha);
708         else if(Gvp.mode==VP_LIGHTEN) *col= mcol_lighten( *col, paintcol, alpha);
709         else if(Gvp.mode==VP_DARKEN) *col= mcol_darken( *col, paintcol, alpha);
710         
711         /* if no spray, clip color adding with colorig & orig alpha */
712         if((Gvp.flag & VP_SPRAY)==0) {
713                 unsigned int testcol=0, a;
714                 char *cp, *ct, *co;
715                 
716                 alpha= (int)(255.0*Gvp.a);
717                 
718                 if(Gvp.mode==VP_MIX || Gvp.mode==VP_BLUR) testcol= mcol_blend( *colorig, paintcol, alpha);
719                 else if(Gvp.mode==VP_ADD) testcol= mcol_add( *colorig, paintcol, alpha);
720                 else if(Gvp.mode==VP_SUB) testcol= mcol_sub( *colorig, paintcol, alpha);
721                 else if(Gvp.mode==VP_MUL) testcol= mcol_mul( *colorig, paintcol, alpha);
722                 else if(Gvp.mode==VP_LIGHTEN)  testcol= mcol_lighten( *colorig, paintcol, alpha);
723                 else if(Gvp.mode==VP_DARKEN)   testcol= mcol_darken( *colorig, paintcol, alpha);
724                 
725                 cp= (char *)col;
726                 ct= (char *)&testcol;
727                 co= (char *)colorig;
728                 
729                 for(a=0; a<4; a++) {
730                         if( ct[a]<co[a] ) {
731                                 if( cp[a]<ct[a] ) cp[a]= ct[a];
732                                 else if( cp[a]>co[a] ) cp[a]= co[a];
733                         }
734                         else {
735                                 if( cp[a]<co[a] ) cp[a]= co[a];
736                                 else if( cp[a]>ct[a] ) cp[a]= ct[a];
737                         }
738                 }
739         }
740 }
741
742
743 static int sample_backbuf_area(VPaint *vp, int *indexar, int totface, int x, int y, float size)
744 {
745         unsigned int *rt;
746         struct ImBuf *ibuf;
747         int x1, y1, x2, y2, a, tot=0, index;
748         
749         if(totface+4>=MAXINDEX) return 0;
750         
751         if(size>64.0) size= 64.0;
752         
753         x1= x-size;
754         x2= x+size;
755         CLAMP(x1, 0, curarea->winx-1);
756         CLAMP(x2, 0, curarea->winx-1);
757         y1= y-size;
758         y2= y+size;
759         CLAMP(y1, 0, curarea->winy-1);
760         CLAMP(y2, 0, curarea->winy-1);
761 #ifdef __APPLE__
762         glReadBuffer(GL_AUX0);
763 #endif
764         
765         if(x1>=x2 || y1>=y2) return 0;
766         
767         ibuf = IMB_allocImBuf(2*size + 4, 2*size + 4, 32, IB_rect, 0);
768         glReadPixels(x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
769         glReadBuffer(GL_BACK);  
770
771         if(G.order==B_ENDIAN)  {
772                 IMB_convert_rgba_to_abgr(ibuf);
773         }
774
775         rt= ibuf->rect;
776         size= (y2-y1)*(x2-x1);
777         if(size<=0) return 0;
778
779         memset(indexar, 0, sizeof(int)*totface+4);      /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */
780         
781         while(size--) {
782                         
783                 if(*rt) {
784                         index= framebuffer_to_index(*rt);
785                         if(index>0 && index<=totface)
786                                 indexar[index] = 1;
787                 }
788         
789                 rt++;
790         }
791         
792         for(a=1; a<=totface; a++) {
793                 if(indexar[a]) indexar[tot++]= a;
794         }
795
796         IMB_freeImBuf(ibuf);
797         
798         return tot;
799 }
800
801 static int calc_vp_alpha_dl(VPaint *vp, float vpimat[][3], float *vert_nor, short *mval)
802 {
803         float fac, dx, dy;
804         int alpha;
805         short vertco[2];
806         
807         if(vp->flag & VP_SOFT) {
808                 project_short_noclip(vert_nor, vertco);
809                 dx= mval[0]-vertco[0];
810                 dy= mval[1]-vertco[1];
811                 
812                 fac= sqrt(dx*dx + dy*dy);
813                 if(fac > vp->size) return 0;
814                 if(vp->flag & VP_HARD)
815                         alpha= 255;
816                 else
817                         alpha= 255.0*vp->a*(1.0-fac/vp->size);
818         }
819         else {
820                 alpha= 255.0*vp->a;
821         }
822
823         if(vp->flag & VP_NORMALS) {
824                 float *no= vert_nor+3;
825                 
826                         /* transpose ! */
827                 fac= vpimat[2][0]*no[0]+vpimat[2][1]*no[1]+vpimat[2][2]*no[2];
828                 if(fac>0.0) {
829                         dx= vpimat[0][0]*no[0]+vpimat[0][1]*no[1]+vpimat[0][2]*no[2];
830                         dy= vpimat[1][0]*no[0]+vpimat[1][1]*no[1]+vpimat[1][2]*no[2];
831                         
832                         alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac);
833                 }
834                 else return 0;
835         }
836         
837         return alpha;
838 }
839
840 static void wpaint_blend(MDeformWeight *dw, MDeformWeight *uw, float alpha, float paintval)
841 {
842         
843         if(dw==NULL || uw==NULL) return;
844         
845         if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR)
846                 dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
847         else if(Gwp.mode==VP_ADD)
848                 dw->weight += paintval*alpha;
849         else if(Gwp.mode==VP_SUB) 
850                 dw->weight -= paintval*alpha;
851         else if(Gwp.mode==VP_MUL) 
852                 /* first mul, then blend the fac */
853                 dw->weight = ((1.0-alpha) + alpha*paintval)*dw->weight;
854         else if(Gwp.mode==VP_LIGHTEN) {
855                 if (dw->weight < paintval)
856                         dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
857         } else if(Gwp.mode==VP_DARKEN) {
858                 if (dw->weight > paintval)
859                         dw->weight = paintval*alpha + dw->weight*(1.0-alpha);
860         }
861         CLAMP(dw->weight, 0.0f, 1.0f);
862         
863         /* if no spray, clip result with orig weight & orig alpha */
864         if((Gwp.flag & VP_SPRAY)==0) {
865                 float testw=0.0f;
866                 
867                 alpha= Gwp.a;
868                 if(Gwp.mode==VP_MIX || Gwp.mode==VP_BLUR)
869                         testw = paintval*alpha + uw->weight*(1.0-alpha);
870                 else if(Gwp.mode==VP_ADD)
871                         testw = uw->weight + paintval*alpha;
872                 else if(Gwp.mode==VP_SUB) 
873                         testw = uw->weight - paintval*alpha;
874                 else if(Gwp.mode==VP_MUL) 
875                         /* first mul, then blend the fac */
876                         testw = ((1.0-alpha) + alpha*paintval)*uw->weight;              
877                 else if(Gwp.mode==VP_LIGHTEN) {
878                         if (uw->weight < paintval)
879                                 testw = paintval*alpha + uw->weight*(1.0-alpha);
880                         else
881                                 testw = uw->weight;
882                 } else if(Gwp.mode==VP_DARKEN) {
883                         if (uw->weight > paintval)
884                                 testw = paintval*alpha + uw->weight*(1.0-alpha);
885                         else
886                                 testw = uw->weight;
887                 }
888                 CLAMP(testw, 0.0f, 1.0f);
889                 
890                 if( testw<uw->weight ) {
891                         if(dw->weight < testw) dw->weight= testw;
892                         else if(dw->weight > uw->weight) dw->weight= uw->weight;
893                 }
894                 else {
895                         if(dw->weight > testw) dw->weight= testw;
896                         else if(dw->weight < uw->weight) dw->weight= uw->weight;
897                 }
898         }
899         
900 }
901
902 /* ----------------------------------------------------- */
903
904 /* used for 3d view, on active object, assumes me->dvert exists */
905 /* if mode==1: */
906 /*     samples cursor location, and gives menu with vertex groups to activate */
907 /* else */
908 /*     sets editbutvweight to the closest weight value to vertex */
909 /*     note: we cant sample frontbuf, weight colors are interpolated too unpredictable */
910 static void sample_wpaint(int mode)
911 {
912         Object *ob= OBACT;
913         Mesh *me= get_mesh(ob);
914         int index;
915         short mval[2], sco[2];
916
917         if (!me) return;
918         
919         getmouseco_areawin(mval);
920         index= sample_backbuf(mval[0], mval[1]);
921         
922         if(index && index<=me->totface) {
923                 MFace *mface;
924                 
925                 mface= ((MFace *)me->mface) + index-1;
926                 
927                 if(mode==1) {   /* sampe which groups are in here */
928                         MDeformVert *dv;
929                         int a, totgroup;
930                         
931                         totgroup= BLI_countlist(&ob->defbase);
932                         if(totgroup) {
933                                 int totmenu=0;
934                                 int *groups=MEM_callocN(totgroup*sizeof(int), "groups");
935                                 
936                                 dv= me->dvert+mface->v1;
937                                 for(a=0; a<dv->totweight; a++) {
938                                         if (dv->dw[a].def_nr<totgroup)
939                                                 groups[dv->dw[a].def_nr]= 1;
940                                 }
941                                 dv= me->dvert+mface->v2;
942                                 for(a=0; a<dv->totweight; a++) {
943                                         if (dv->dw[a].def_nr<totgroup)
944                                                 groups[dv->dw[a].def_nr]= 1;
945                                 }
946                                 dv= me->dvert+mface->v3;
947                                 for(a=0; a<dv->totweight; a++) {
948                                         if (dv->dw[a].def_nr<totgroup)
949                                                 groups[dv->dw[a].def_nr]= 1;
950                                 }
951                                 if(mface->v4) {
952                                         dv= me->dvert+mface->v4;
953                                         for(a=0; a<dv->totweight; a++) {
954                                                 if (dv->dw[a].def_nr<totgroup)
955                                                         groups[dv->dw[a].def_nr]= 1;
956                                         }
957                                 }
958                                 for(a=0; a<totgroup; a++)
959                                         if(groups[a]) totmenu++;
960                                 
961                                 if(totmenu==0) {
962                                         notice("No Vertex Group Selected");
963                                 }
964                                 else {
965                                         bDeformGroup *dg;
966                                         short val;
967                                         char item[40], *str= MEM_mallocN(40*totmenu+40, "menu");
968                                         
969                                         strcpy(str, "Vertex Groups %t");
970                                         for(a=0, dg=ob->defbase.first; dg && a<totgroup; a++, dg= dg->next) {
971                                                 if(groups[a]) {
972                                                         sprintf(item, "|%s %%x%d", dg->name, a);
973                                                         strcat(str, item);
974                                                 }
975                                         }
976                                         
977                                         val= pupmenu(str);
978                                         if(val>=0) {
979                                                 ob->actdef= val+1;
980                                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
981                                                 allqueue(REDRAWVIEW3D, 0);
982                                                 allqueue(REDRAWOOPS, 0);
983                                                 allqueue(REDRAWBUTSEDIT, 0);
984                                         }
985                                         MEM_freeN(str);
986                                 }
987                                 MEM_freeN(groups);
988                         }
989                         else notice("No Vertex Groups in Object");
990                 }
991                 else {
992                         DerivedMesh *dm;
993                         MDeformWeight *dw;
994                         extern float editbutvweight;
995                         float w1, w2, w3, w4, co[3], fac;
996                         
997                         dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
998                         if(dm->getVertCo==NULL) {
999                                 notice("Not supported yet");
1000                         }
1001                         else {
1002                                 /* calc 3 or 4 corner weights */
1003                                 dm->getVertCo(dm, mface->v1, co);
1004                                 project_short_noclip(co, sco);
1005                                 w1= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1006                                 
1007                                 dm->getVertCo(dm, mface->v2, co);
1008                                 project_short_noclip(co, sco);
1009                                 w2= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1010                                 
1011                                 dm->getVertCo(dm, mface->v3, co);
1012                                 project_short_noclip(co, sco);
1013                                 w3= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1014                                 
1015                                 if(mface->v4) {
1016                                         dm->getVertCo(dm, mface->v4, co);
1017                                         project_short_noclip(co, sco);
1018                                         w4= ((mval[0]-sco[0])*(mval[0]-sco[0]) + (mval[1]-sco[1])*(mval[1]-sco[1]));
1019                                 }
1020                                 else w4= 1.0e10;
1021                                 
1022                                 fac= MIN4(w1, w2, w3, w4);
1023                                 if(w1==fac) {
1024                                         dw= get_defweight(me->dvert+mface->v1, ob->actdef-1);
1025                                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1026                                 }
1027                                 else if(w2==fac) {
1028                                         dw= get_defweight(me->dvert+mface->v2, ob->actdef-1);
1029                                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1030                                 }
1031                                 else if(w3==fac) {
1032                                         dw= get_defweight(me->dvert+mface->v3, ob->actdef-1);
1033                                         if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1034                                 }
1035                                 else if(w4==fac) {
1036                                         if(mface->v4) {
1037                                                 dw= get_defweight(me->dvert+mface->v4, ob->actdef-1);
1038                                                 if(dw) editbutvweight= dw->weight; else editbutvweight= 0.0f;
1039                                         }
1040                                 }
1041                         }
1042                         dm->release(dm);
1043                 }               
1044                 
1045         }
1046         allqueue(REDRAWBUTSEDIT, 0);
1047         
1048 }
1049
1050 static void do_weight_paint_vertex(Object *ob, int index, int alpha, float paintweight, int vgroup_mirror)
1051 {
1052         Mesh *me= ob->data;
1053         MDeformWeight   *dw, *uw;
1054         int vgroup= ob->actdef-1;
1055         
1056         if(Gwp.flag & VP_ONLYVGROUP) {
1057                 dw= get_defweight(me->dvert+index, vgroup);
1058                 uw= get_defweight(Gwp.wpaint_prev+index, vgroup);
1059         }
1060         else {
1061                 dw= verify_defweight(me->dvert+index, vgroup);
1062                 uw= verify_defweight(Gwp.wpaint_prev+index, vgroup);
1063         }
1064         if(dw==NULL || uw==NULL)
1065                 return;
1066         
1067         wpaint_blend(dw, uw, (float)alpha/255.0, paintweight);
1068         
1069         if(Gwp.flag & VP_MIRROR_X) {    /* x mirror painting */
1070                 int j= mesh_get_x_mirror_vert(ob, index);
1071                 if(j>=0) {
1072                         /* copy, not paint again */
1073                         if(vgroup_mirror != -1)
1074                                 uw= verify_defweight(me->dvert+j, vgroup_mirror);
1075                         else
1076                                 uw= verify_defweight(me->dvert+j, vgroup);
1077                                 
1078                         uw->weight= dw->weight;
1079                 }
1080         }
1081 }
1082
1083 void weight_paint(void)
1084 {
1085         extern float editbutvweight;
1086         Object *ob; 
1087         Mesh *me;
1088         MFace *mface;
1089         float mat[4][4], imat[4][4], paintweight, *vertexcosnos;
1090         float vpimat[3][3];
1091         int *indexar, index, totindex, alpha, totw;
1092         int vgroup_mirror= -1;
1093         short mval[2], mvalo[2], firsttime=1;
1094
1095         if((G.f & G_WEIGHTPAINT)==0) return;
1096         if(G.obedit) return;
1097         if(multires_level1_test()) return;
1098         
1099         ob= OBACT;
1100         if(!ob || ob->id.lib) return;
1101
1102         me= get_mesh(ob);
1103         if(me==NULL || me->totface==0) return;
1104         
1105         /* if nothing was added yet, we make dverts and a vertex deform group */
1106         if (!me->dvert)
1107                 create_dverts(&me->id);
1108         
1109         if(G.qual & LR_CTRLKEY) {
1110                 sample_wpaint(0);
1111                 return;
1112         }
1113         if(G.qual & LR_SHIFTKEY) {
1114                 sample_wpaint(1);
1115                 return;
1116         }
1117         
1118         /* ALLOCATIONS! no return after this line */
1119                 /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1120         vertexcosnos= mesh_get_mapped_verts_nors(ob);
1121         indexar= get_indexarray();
1122         copy_wpaint_prev(&Gwp, me->dvert, me->totvert);
1123
1124         /* this happens on a Bone select, when no vgroup existed yet */
1125         if(ob->actdef<=0) {
1126                 Object *modob;
1127                 if((modob = modifiers_isDeformedByArmature(ob))) {
1128                         bPoseChannel *pchan;
1129                         for(pchan= modob->pose->chanbase.first; pchan; pchan= pchan->next)
1130                                 if(pchan->bone->flag & SELECT)
1131                                         break;
1132                         if(pchan) {
1133                                 bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name);
1134                                 if(dg==NULL)
1135                                         dg= add_defgroup_name(ob, pchan->name); /* sets actdef */
1136                                 else
1137                                         ob->actdef= get_defgroup_num(ob, dg);
1138                                 allqueue(REDRAWBUTSEDIT, 0);
1139                         }
1140                 }
1141         }
1142         if(ob->defbase.first==NULL) {
1143                 add_defgroup(ob);
1144                 allqueue(REDRAWBUTSEDIT, 0);
1145         }       
1146         
1147         if(ob->lay & G.vd->lay); else error("Active object is not in this layer");
1148         
1149         persp(PERSP_VIEW);
1150         /* imat for normals */
1151         Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
1152         Mat4Invert(imat, mat);
1153         Mat3CpyMat4(vpimat, imat);
1154         
1155         /* load projection matrix */
1156         mymultmatrix(ob->obmat);
1157         mygetsingmatrix(mat);
1158         myloadmatrix(G.vd->viewmat);
1159         
1160         getmouseco_areawin(mvalo);
1161         
1162         getmouseco_areawin(mval);
1163         mvalo[0]= mval[0];
1164         mvalo[1]= mval[1];
1165         
1166         /* if mirror painting, find the other group */
1167         if(Gwp.flag & VP_MIRROR_X) {
1168                 bDeformGroup *defgroup= BLI_findlink(&ob->defbase, ob->actdef-1);
1169                 if(defgroup) {
1170                         bDeformGroup *curdef;
1171                         int actdef= 0;
1172                         char name[32];
1173
1174                         BLI_strncpy(name, defgroup->name, 32);
1175                         bone_flip_name(name, 0);                /* 0 = don't strip off number extensions */
1176                         
1177                         for (curdef = ob->defbase.first; curdef; curdef=curdef->next, actdef++)
1178                                 if (!strcmp(curdef->name, name))
1179                                         break;
1180                         if(curdef==NULL) {
1181                                 int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
1182                                 curdef= add_defgroup_name (ob, name);
1183                                 ob->actdef= olddef;
1184                         }
1185                         
1186                         if(curdef && curdef!=defgroup)
1187                                 vgroup_mirror= actdef;
1188                 }
1189         }
1190         
1191         while (get_mbut() & L_MOUSE) {
1192                 getmouseco_areawin(mval);
1193                 
1194                 if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1195                         firsttime= 0;
1196                         
1197                         /* which faces are involved */
1198                         if(Gwp.flag & VP_AREA) {
1199                                 totindex= sample_backbuf_area(&Gwp, indexar, me->totface, mval[0], mval[1], Gwp.size);
1200                         }
1201                         else {
1202                                 indexar[0]= sample_backbuf(mval[0], mval[1]);
1203                                 if(indexar[0]) totindex= 1;
1204                                 else totindex= 0;
1205                         }
1206                         
1207                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1208                         
1209                         if(Gwp.flag & VP_COLINDEX) {
1210                                 for(index=0; index<totindex; index++) {
1211                                         if(indexar[index] && indexar[index]<=me->totface) {
1212                                         
1213                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1214                                         
1215                                                 if(mface->mat_nr!=ob->actcol-1) {
1216                                                         indexar[index]= 0;
1217                                                 }
1218                                         }                                       
1219                                 }
1220                         }
1221
1222                         if((G.f & G_FACESELECT) && me->mface) {
1223                                 for(index=0; index<totindex; index++) {
1224                                         if(indexar[index] && indexar[index]<=me->totface) {
1225                                         
1226                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1227                                         
1228                                                 if((mface->flag & ME_FACE_SEL)==0) {
1229                                                         indexar[index]= 0;
1230                                                 }
1231                                         }                                       
1232                                 }
1233                         }
1234                         
1235                         /* make sure each vertex gets treated only once */
1236                         /* and calculate filter weight */
1237                         totw= 0;
1238                         if(Gwp.mode==VP_BLUR) 
1239                                 paintweight= 0.0f;
1240                         else
1241                                 paintweight= editbutvweight;
1242                         
1243                         for(index=0; index<totindex; index++) {
1244                                 if(indexar[index] && indexar[index]<=me->totface) {
1245                                         mface= me->mface + (indexar[index]-1);
1246                                         
1247                                         (me->dvert+mface->v1)->flag= 1;
1248                                         (me->dvert+mface->v2)->flag= 1;
1249                                         (me->dvert+mface->v3)->flag= 1;
1250                                         if(mface->v4) (me->dvert+mface->v4)->flag= 1;
1251                                         
1252                                         if(Gwp.mode==VP_BLUR) {
1253                                                 MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight;
1254                                                 
1255                                                 if(Gwp.flag & VP_ONLYVGROUP)
1256                                                         dw_func= get_defweight;
1257                                                 
1258                                                 dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
1259                                                 if(dw) {paintweight+= dw->weight; totw++;}
1260                                                 dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
1261                                                 if(dw) {paintweight+= dw->weight; totw++;}
1262                                                 dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
1263                                                 if(dw) {paintweight+= dw->weight; totw++;}
1264                                                 if(mface->v4) {
1265                                                         dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
1266                                                         if(dw) {paintweight+= dw->weight; totw++;}
1267                                                 }
1268                                         }
1269                                 }
1270                         }
1271                         
1272                         if(Gwp.mode==VP_BLUR) 
1273                                 paintweight/= (float)totw;
1274                         
1275                         for(index=0; index<totindex; index++) {
1276                                 
1277                                 if(indexar[index] && indexar[index]<=me->totface) {
1278                                         mface= me->mface + (indexar[index]-1);
1279                                         
1280                                         if((me->dvert+mface->v1)->flag) {
1281                                                 alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v1, mval);
1282                                                 if(alpha) {
1283                                                         do_weight_paint_vertex(ob, mface->v1, alpha, paintweight, vgroup_mirror);
1284                                                 }
1285                                                 (me->dvert+mface->v1)->flag= 0;
1286                                         }
1287                                         
1288                                         if((me->dvert+mface->v2)->flag) {
1289                                                 alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v2, mval);
1290                                                 if(alpha) {
1291                                                         do_weight_paint_vertex(ob, mface->v2, alpha, paintweight, vgroup_mirror);
1292                                                 }
1293                                                 (me->dvert+mface->v2)->flag= 0;
1294                                         }
1295                                         
1296                                         if((me->dvert+mface->v3)->flag) {
1297                                                 alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v3, mval);
1298                                                 if(alpha) {
1299                                                         do_weight_paint_vertex(ob, mface->v3, alpha, paintweight, vgroup_mirror);
1300                                                 }
1301                                                 (me->dvert+mface->v3)->flag= 0;
1302                                         }
1303                                         
1304                                         if((me->dvert+mface->v4)->flag) {
1305                                                 if(mface->v4) {
1306                                                         alpha= calc_vp_alpha_dl(&Gwp, vpimat, vertexcosnos+6*mface->v4, mval);
1307                                                         if(alpha) {
1308                                                                 do_weight_paint_vertex(ob, mface->v4, alpha, paintweight, vgroup_mirror);
1309                                                         }
1310                                                         (me->dvert+mface->v4)->flag= 0;
1311                                                 }
1312                                         }
1313                                 }
1314                         }
1315                         
1316                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1317                         
1318                 }
1319                 else BIF_wait_for_statechange();
1320                 
1321                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1322
1323                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1324                         scrarea_do_windraw(curarea);
1325                         
1326                         if(Gwp.flag & (VP_AREA|VP_SOFT)) {
1327                                 /* draw circle in backbuf! */
1328                                 persp(PERSP_WIN);
1329                                 fdrawXORcirc((float)mval[0], (float)mval[1], Gwp.size);
1330                                 persp(PERSP_VIEW);
1331                         }
1332
1333                         screen_swapbuffers();
1334                         backdrawview3d(0);
1335         
1336                         mvalo[0]= mval[0];
1337                         mvalo[1]= mval[1];
1338                 }
1339         }
1340         
1341         if(vertexcosnos)
1342                 MEM_freeN(vertexcosnos);
1343         MEM_freeN(indexar);
1344         copy_wpaint_prev(&Gwp, NULL, 0);
1345
1346         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1347
1348         /* and particles too */
1349         if(ob->particlesystem.first) {
1350                 ParticleSystem *psys;
1351                 int i;
1352
1353                 psys= ob->particlesystem.first;
1354                 while(psys) {
1355                         for(i=0; i<PSYS_TOT_VG; i++) {
1356                                 if(psys->vgroup[i]==ob->actdef) {
1357                                         psys->recalc |= PSYS_RECALC_HAIR;
1358                                         break;
1359                                 }
1360                         }
1361
1362                         psys= psys->next;
1363                 }
1364         }
1365         
1366         BIF_undo_push("Weight Paint");
1367         allqueue(REDRAWVIEW3D, 0);
1368 }
1369
1370 void vertex_paint()
1371 {
1372         Object *ob;
1373         Mesh *me;
1374         MFace *mface;
1375         float mat[4][4], imat[4][4], *vertexcosnos;
1376         float vpimat[3][3];
1377         unsigned int paintcol=0, *mcol, *mcolorig, fcol1, fcol2;
1378         int *indexar, index, alpha, totindex;
1379         short mval[2], mvalo[2], firsttime=1;
1380         
1381         if((G.f & G_VERTEXPAINT)==0) return;
1382         if(G.obedit) return;
1383         
1384         ob= OBACT;
1385         if(!ob || ob->id.lib) return;
1386
1387         me= get_mesh(ob);
1388         if(me==NULL || me->totface==0) return;
1389         if(ob->lay & G.vd->lay); else error("Active object is not in this layer");
1390         
1391         if(me->mcol==NULL) make_vertexcol(0);
1392
1393         if(me->mcol==NULL) return;
1394         
1395         /* ALLOCATIONS! No return after his line */
1396         
1397                                 /* painting on subsurfs should give correct points too, this returns me->totvert amount */
1398         vertexcosnos= mesh_get_mapped_verts_nors(ob);
1399         indexar= get_indexarray();
1400         copy_vpaint_prev(&Gvp, (unsigned int *)me->mcol, me->totface);
1401         
1402         /* opengl/matrix stuff */
1403         persp(PERSP_VIEW);
1404         /* imat for normals */
1405         Mat4MulMat4(mat, ob->obmat, G.vd->viewmat);
1406         Mat4Invert(imat, mat);
1407         Mat3CpyMat4(vpimat, imat);
1408         
1409         /* load projection matrix */
1410         mymultmatrix(ob->obmat);
1411         mygetsingmatrix(mat);
1412         myloadmatrix(G.vd->viewmat);
1413         
1414         paintcol= vpaint_get_current_col(&Gvp);
1415         
1416         getmouseco_areawin(mvalo);
1417         
1418         getmouseco_areawin(mval);
1419         mvalo[0]= mval[0];
1420         mvalo[1]= mval[1];
1421         
1422         while (get_mbut() & L_MOUSE) {
1423                 getmouseco_areawin(mval);
1424                 
1425                 if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) {
1426
1427                         firsttime= 0;
1428
1429                         /* which faces are involved */
1430                         if(Gvp.flag & VP_AREA) {
1431                                 totindex= sample_backbuf_area(&Gvp, indexar, me->totface, mval[0], mval[1], Gvp.size);
1432                         }
1433                         else {
1434                                 indexar[0]= sample_backbuf(mval[0], mval[1]);
1435                                 if(indexar[0]) totindex= 1;
1436                                 else totindex= 0;
1437                         }
1438                         
1439                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1440                         
1441                         if(Gvp.flag & VP_COLINDEX) {
1442                                 for(index=0; index<totindex; index++) {
1443                                         if(indexar[index] && indexar[index]<=me->totface) {
1444                                         
1445                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1446                                         
1447                                                 if(mface->mat_nr!=ob->actcol-1) {
1448                                                         indexar[index]= 0;
1449                                                 }
1450                                         }                                       
1451                                 }
1452                         }
1453                         if((G.f & G_FACESELECT) && me->mface) {
1454                                 for(index=0; index<totindex; index++) {
1455                                         if(indexar[index] && indexar[index]<=me->totface) {
1456                                                 mface= ((MFace *)me->mface) + (indexar[index]-1);
1457                                         
1458                                                 if((mface->flag & ME_FACE_SEL)==0)
1459                                                         indexar[index]= 0;
1460                                         }                                       
1461                                 }
1462                         }
1463
1464                         for(index=0; index<totindex; index++) {
1465
1466                                 if(indexar[index] && indexar[index]<=me->totface) {
1467                                 
1468                                         mface= ((MFace *)me->mface) + (indexar[index]-1);
1469                                         mcol=     ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
1470                                         mcolorig= ( (unsigned int *)Gvp.vpaint_prev) + 4*(indexar[index]-1);
1471
1472                                         if(Gvp.mode==VP_BLUR) {
1473                                                 fcol1= mcol_blend( mcol[0], mcol[1], 128);
1474                                                 if(mface->v4) {
1475                                                         fcol2= mcol_blend( mcol[2], mcol[3], 128);
1476                                                         paintcol= mcol_blend( fcol1, fcol2, 128);
1477                                                 }
1478                                                 else {
1479                                                         paintcol= mcol_blend( mcol[2], fcol1, 170);
1480                                                 }
1481                                                 
1482                                         }
1483                                         
1484                                         alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v1, mval);
1485                                         if(alpha) vpaint_blend( mcol, mcolorig, paintcol, alpha);
1486                                         
1487                                         alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v2, mval);
1488                                         if(alpha) vpaint_blend( mcol+1, mcolorig+1, paintcol, alpha);
1489         
1490                                         alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v3, mval);
1491                                         if(alpha) vpaint_blend( mcol+2, mcolorig+2, paintcol, alpha);
1492
1493                                         if(mface->v4) {
1494                                                 alpha= calc_vp_alpha_dl(&Gvp, vpimat, vertexcosnos+6*mface->v4, mval);
1495                                                 if(alpha) vpaint_blend( mcol+3, mcolorig+3, paintcol, alpha);
1496                                         }
1497                                 }
1498                         }
1499                                 
1500                         MTC_Mat4SwapMat4(G.vd->persmat, mat);
1501                         
1502                         do_shared_vertexcol(me);
1503         
1504                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1505                         scrarea_do_windraw(curarea);
1506
1507                         if(Gvp.flag & (VP_AREA|VP_SOFT)) {
1508                                 /* draw circle in backbuf! */
1509                                 persp(PERSP_WIN);
1510                                 fdrawXORcirc((float)mval[0], (float)mval[1], Gvp.size);
1511                                 persp(PERSP_VIEW);
1512                         }
1513                         screen_swapbuffers();
1514                         backdrawview3d(0);
1515                         
1516                         mvalo[0]= mval[0];
1517                         mvalo[1]= mval[1];
1518                 }
1519                 else BIF_wait_for_statechange();
1520         }
1521         
1522         if(vertexcosnos)
1523                 MEM_freeN(vertexcosnos);
1524         MEM_freeN(indexar);
1525         
1526         /* frees prev buffer */
1527         copy_vpaint_prev(&Gvp, NULL, 0);
1528
1529         BIF_undo_push("Vertex Paint");
1530         
1531         allqueue(REDRAWVIEW3D, 0);
1532 }
1533
1534 void set_wpaint(void)           /* toggle */
1535 {               
1536         Object *ob;
1537         Mesh *me;
1538         
1539         scrarea_queue_headredraw(curarea);
1540         ob= OBACT;
1541         if(!ob || ob->id.lib) return;
1542         me= get_mesh(ob);
1543                 
1544         if(me && me->totface>=MAXINDEX) {
1545                 error("Maximum number of faces: %d", MAXINDEX-1);
1546                 G.f &= ~G_WEIGHTPAINT;
1547                 return;
1548         }
1549         
1550         if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT;
1551         else G.f |= G_WEIGHTPAINT;
1552         
1553         allqueue(REDRAWVIEW3D, 1);      /* including header */
1554         allqueue(REDRAWBUTSEDIT, 0);
1555         
1556                 /* Weightpaint works by overriding colors in mesh,
1557                  * so need to make sure we recalc on enter and
1558                  * exit (exit needs doing regardless because we
1559                  * should redeform).
1560                  */
1561         if (me) {
1562                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1563         }
1564
1565         if(G.f & G_WEIGHTPAINT) {
1566                 Object *par;
1567                 
1568                 setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
1569                 
1570                 mesh_octree_table(ob, NULL, 's');
1571
1572                 /* verify if active weight group is also active bone */
1573                 par= modifiers_isDeformedByArmature(ob);
1574                 if(par && (par->flag & OB_POSEMODE)) {
1575                         bPoseChannel *pchan;
1576                         for(pchan= par->pose->chanbase.first; pchan; pchan= pchan->next)
1577                                 if(pchan->bone->flag & BONE_ACTIVE)
1578                                         break;
1579                         if(pchan)
1580                                 vertexgroup_select_by_name(ob, pchan->name);
1581                 }
1582         }
1583         else {
1584                 if(!(G.f & G_FACESELECT))
1585                         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1586                 
1587                 mesh_octree_table(ob, NULL, 'e');
1588         }
1589 }
1590
1591
1592 void set_vpaint(void)           /* toggle */
1593 {               
1594         Object *ob;
1595         Mesh *me;
1596         
1597         scrarea_queue_headredraw(curarea);
1598         ob= OBACT;
1599         if(!ob || object_data_is_libdata(ob)) {
1600                 G.f &= ~G_VERTEXPAINT;
1601                 return;
1602         }
1603         
1604         me= get_mesh(ob);
1605         
1606         if(me && me->totface>=MAXINDEX) {
1607                 error("Maximum number of faces: %d", MAXINDEX-1);
1608                 G.f &= ~G_VERTEXPAINT;
1609                 return;
1610         }
1611         
1612         if(me && me->mcol==NULL) make_vertexcol(0);
1613         
1614         if(G.f & G_VERTEXPAINT){
1615                 G.f &= ~G_VERTEXPAINT;
1616         }
1617         else {
1618                 G.f |= G_VERTEXPAINT;
1619                 /* Turn off weight painting */
1620                 if (G.f & G_WEIGHTPAINT)
1621                         set_wpaint();
1622         }
1623         
1624         allqueue(REDRAWVIEW3D, 1);      /* including header */
1625         allqueue(REDRAWBUTSEDIT, 0);
1626         
1627         if (me)
1628                 /* update modifier stack for mapping requirements */
1629                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1630
1631         if(G.f & G_VERTEXPAINT) {
1632                 setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT);
1633         }
1634         else {
1635                 if((G.f & G_FACESELECT)==0) setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1636         }
1637 }
1638