diff options
Diffstat (limited to 'source/blender/src/vpaint.c')
-rw-r--r-- | source/blender/src/vpaint.c | 1169 |
1 files changed, 1169 insertions, 0 deletions
diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c new file mode 100644 index 00000000000..d6e8e9b2654 --- /dev/null +++ b/source/blender/src/vpaint.c @@ -0,0 +1,1169 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> + +#ifdef WIN32 +#include <io.h> +#include "BLI_winstuff.h" +#else +#include <unistd.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" +#include "MTC_matrixops.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" + +#include "BKE_utildefines.h" +#include "BKE_mesh.h" +#include "BKE_displist.h" +#include "BKE_global.h" + +#include "BIF_graphics.h" +#include "BIF_interface.h" +#include "BIF_mywindow.h" +#include "BIF_editview.h" +#include "BIF_space.h" +#include "BIF_screen.h" +#include "BIF_toolbox.h" +#include "BIF_gl.h" + +#include "BDR_vpaint.h" + +#include "BSE_drawview.h" +#include "BSE_trans_types.h" +#include "BSE_view.h" + +#include "mydevice.h" +#include "blendef.h" + +#include "BIF_editdeform.h" + + /* Gvp.mode */ +#define VP_MIX 0 +#define VP_ADD 1 +#define VP_SUB 2 +#define VP_MUL 3 +#define VP_FILT 4 + + /* Gvp.flag */ +#define VP_COLINDEX 1 +#define VP_AREA 2 +#define VP_SOFT 4 +#define VP_NORMALS 8 + +#define MAXINDEX 65336 + +VPaint Gvp= {1.0, 1.0, 1.0, 0.2, 25.0, 1.0, 1.0, 0, VP_AREA+VP_SOFT}; +float vpimat[3][3]; +unsigned int *vpaintundobuf=0; +int totvpaintundo; +short *indexar= 0; + +int totwpaintundo; +MDeformVert *wpaintundobuf=NULL; + +/* Function prototypes */ +int calc_vp_alpha_dl(DispList *disp, MVert *mvert, int vert, short *mval); + +/* in tegenstelling tot cpack teken kleuren, zijn de MCOL kleuren (vpaint kleuren) per byte! + en dus endian ongevoelig. Mcol = ABGR!!! Oppassen met cpack functies */ + +unsigned int rgba_to_mcol(float r, float g, float b, float a) +{ + int ir, ig, ib, ia; + unsigned int col; + char *cp; + + ir= floor(255.0*r); + if(ir<0) ir= 0; else if(ir>255) ir= 255; + ig= floor(255.0*g); + if(ig<0) ig= 0; else if(ig>255) ig= 255; + ib= floor(255.0*b); + if(ib<0) ib= 0; else if(ib>255) ib= 255; + ia= floor(255.0*a); + if(ia<0) ia= 0; else if(ia>255) ia= 255; + + cp= (char *)&col; + cp[0]= ia; + cp[1]= ib; + cp[2]= ig; + cp[3]= ir; + + return col; + +} + +unsigned int vpaint_get_current_col(void) +{ + return rgba_to_mcol(Gvp.r, Gvp.g, Gvp.b, 1.0); +} + +void do_shared_vertexcol(Mesh *me) +{ + /* als geen mcol: niet doen */ + /* als tface: alleen de betreffende vlakken, anders alles */ + MFace *mface; + TFace *tface; + int a; + short *scolmain, *scol; + char *mcol; + + if(me->mcol==0 || me->totvert==0 || me->totface==0) return; + + scolmain= MEM_callocN(4*sizeof(short)*me->totvert, "colmain"); + + tface= me->tface; + mface= me->mface; + mcol= (char *)me->mcol; + for(a=me->totface; a>0; a--, mface++, mcol+=16) { + if(mface->v3) { + if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) { + + scol= scolmain+4*mface->v1; + scol[0]++; scol[1]+= mcol[1]; scol[2]+= mcol[2]; scol[3]+= mcol[3]; + scol= scolmain+4*mface->v2; + scol[0]++; scol[1]+= mcol[5]; scol[2]+= mcol[6]; scol[3]+= mcol[7]; + scol= scolmain+4*mface->v3; + scol[0]++; scol[1]+= mcol[9]; scol[2]+= mcol[10]; scol[3]+= mcol[11]; + if(mface->v4) { + scol= scolmain+4*mface->v4; + scol[0]++; scol[1]+= mcol[13]; scol[2]+= mcol[14]; scol[3]+= mcol[15]; + } + } + } + if(tface) tface++; + } + + a= me->totvert; + scol= scolmain; + while(a--) { + if(scol[0]>1) { + scol[1]/= scol[0]; + scol[2]/= scol[0]; + scol[3]/= scol[0]; + } + scol+= 4; + } + + tface= me->tface; + mface= me->mface; + mcol= (char *)me->mcol; + for(a=me->totface; a>0; a--, mface++, mcol+=16) { + if(mface->v3) { + if(tface==0 || (tface->mode & TF_SHAREDCOL) || (G.f & G_FACESELECT)==0) { + + scol= scolmain+4*mface->v1; + mcol[1]= scol[1]; mcol[2]= scol[2]; mcol[3]= scol[3]; + + scol= scolmain+4*mface->v2; + mcol[5]= scol[1]; mcol[6]= scol[2]; mcol[7]= scol[3]; + + scol= scolmain+4*mface->v3; + mcol[9]= scol[1]; mcol[10]= scol[2]; mcol[11]= scol[3]; + + if(mface->v4) { + scol= scolmain+4*mface->v4; + mcol[13]= scol[1]; mcol[14]= scol[2]; mcol[15]= scol[3]; + } + } + } + if(tface) tface++; + } + + MEM_freeN(scolmain); +} + +void make_vertexcol() /* single ob */ +{ + Object *ob; + Mesh *me; + DispList *dl; + + /* + * Always copies from shadedisplist to mcol. + * When there are tfaces, it copies the colors and frees mcol + */ + + if(G.obedit) { + error("Unable to perform function in EditMode"); + return; + } + + ob= OBACT; + me= get_mesh(ob); + if(me==0) return; + + if(me->flag & ME_TWOSIDED) { + me->flag &= ~ME_TWOSIDED; + } + + dl= ob->disp.first; + + if(dl==0 || dl->col1==NULL) { + shadeDispList(ob); + dl= ob->disp.first; + } + if(dl && dl->col1) { + int i; + + if(me->mcol) MEM_freeN(me->mcol); + + me->mcol= MEM_dupallocN(dl->col1); + if (me->mcol) { + for (i=0; i<me->totface*4; i++) { + MCol *mcol= &me->mcol[i]; + mcol->a= 255; + } + } + + if(me->tface) mcol_to_tface(me, 1); + } + freedisplist(&(ob->disp)); + + + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); +} + + + +void copy_vpaint_undo(unsigned int *mcol, int tot) +{ + if(vpaintundobuf) MEM_freeN(vpaintundobuf); + vpaintundobuf= 0; + + if(mcol==0 || tot==0) return; + + vpaintundobuf= MEM_mallocN(4*sizeof(int)*tot, "vpaintundobuf"); + memcpy(vpaintundobuf, mcol, 4*sizeof(int)*tot); + totvpaintundo= tot; + +} + +void vpaint_undo() +{ + Mesh *me; + Object *ob; + unsigned int temp, *from, *to; + int a; + + if((G.f & G_VERTEXPAINT)==0) return; + if(vpaintundobuf==0) return; + + ob= OBACT; + me= get_mesh(ob); + if(me==0 || me->totface==0) return; + + if(me->tface) tface_to_mcol(me); + else if(me->mcol==0) return; + + a= MIN2(me->totface, totvpaintundo); + from= vpaintundobuf; + to= (unsigned int *)me->mcol; + a*= 4; + while(a--) { + temp= *to; + *to= *from; + *from= temp; + to++; from++; + } + allqueue(REDRAWVIEW3D, 0); + if(me->tface) mcol_to_tface(me, 1); +} + +void clear_vpaint() +{ + Mesh *me; + Object *ob; + unsigned int *to, paintcol; + int a; + + if((G.f & G_VERTEXPAINT)==0) return; + + ob= OBACT; + me= get_mesh(ob); + if(me==0 || me->totface==0) return; + + if(me->tface) tface_to_mcol(me); + if(me->mcol==0) return; + + paintcol= vpaint_get_current_col(); + + to= (unsigned int *)me->mcol; + copy_vpaint_undo(to, me->totface); + a= 4*me->totface; + while(a--) { + *to= paintcol; + to++; + } + allqueue(REDRAWVIEW3D, 0); + if(me->tface) mcol_to_tface(me, 1); +} + +void clear_vpaint_selectedfaces() +{ + Mesh *me; + TFace *tf; + Object *ob; + unsigned int paintcol; + int i; + + ob= OBACT; + + me= get_mesh(ob); + tf = me->tface; + if (!tf) return; /* should not happen, but you never know */ + + if(me==0 || me->totface==0) return; + + paintcol= vpaint_get_current_col(); + + for (i = 0; i < me->totface; i++) { + if (tf[i].flag & TF_SELECT) { + tf[i].col[0] = paintcol; + tf[i].col[1] = paintcol; + tf[i].col[2] = paintcol; + tf[i].col[3] = paintcol; + } + } + allqueue(REDRAWVIEW3D, 0); +} + +void vpaint_dogamma() +{ + Mesh *me; + Object *ob; + float igam, fac; + int a, temp; + char *cp, gamtab[256]; + + if((G.f & G_VERTEXPAINT)==0) return; + + ob= OBACT; + me= get_mesh(ob); + if(me==0 || me->totface==0) return; + + if(me->tface) tface_to_mcol(me); + else if(me->mcol==0) return; + + copy_vpaint_undo((unsigned int *)me->mcol, me->totface); + + igam= 1.0/Gvp.gamma; + for(a=0; a<256; a++) { + + fac= ((float)a)/255.0; + fac= Gvp.mul*pow( fac, igam); + + temp= 255.9*fac; + + if(temp<=0) gamtab[a]= 0; + else if(temp>=255) gamtab[a]= 255; + else gamtab[a]= temp; + } + + a= 4*me->totface; + cp= (char *)me->mcol; + while(a--) { + + cp[1]= gamtab[ cp[1] ]; + cp[2]= gamtab[ cp[2] ]; + cp[3]= gamtab[ cp[3] ]; + + cp+= 4; + } + allqueue(REDRAWVIEW3D, 0); + + if(me->tface) mcol_to_tface(me, 1); +} + + +void sample_vpaint() /* frontbuf */ +{ + unsigned int col; + int x, y; + short mval[2]; + char *cp; + + getmouseco_areawin(mval); + x= mval[0]; y= mval[1]; + + if(x<0 || y<0) return; + if(x>=curarea->winx || y>=curarea->winy) return; + + x+= curarea->winrct.xmin; + y+= curarea->winrct.ymin; + + glReadBuffer(GL_FRONT); + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + glReadBuffer(GL_BACK); + + cp = (char *)&col; + + Gvp.r= cp[0]; + Gvp.r /= 255.0; + + Gvp.g= cp[1]; + Gvp.g /= 255.0; + + Gvp.b= cp[2]; + Gvp.b /= 255.0; + + allqueue(REDRAWBUTSGAME, 0); +} + +void init_vertexpaint() +{ + + indexar= MEM_mallocN(sizeof(short)*MAXINDEX + 2, "vertexpaint"); +} + + +void free_vertexpaint() +{ + + if(indexar) MEM_freeN(indexar); + indexar= NULL; + if(vpaintundobuf) MEM_freeN(vpaintundobuf); + vpaintundobuf= NULL; + if(wpaintundobuf) + free_dverts(wpaintundobuf, totwpaintundo); + wpaintundobuf= NULL; +} + + +static unsigned int mcol_blend(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int mfac; + unsigned int col=0; + + if(fac==0) return col1; + if(fac>=255) return col2; + + mfac= 255-fac; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= 255; + cp[1]= (mfac*cp1[1]+fac*cp2[1])>>8; + cp[2]= (mfac*cp1[2]+fac*cp2[2])>>8; + cp[3]= (mfac*cp1[3]+fac*cp2[3])>>8; + + return col; +} + +static unsigned int mcol_add(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int temp; + unsigned int col=0; + + if(fac==0) return col1; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= 255; + temp= cp1[1] + ((fac*cp2[1])>>8); + if(temp>254) cp[1]= 255; else cp[1]= temp; + temp= cp1[2] + ((fac*cp2[2])>>8); + if(temp>254) cp[2]= 255; else cp[2]= temp; + temp= cp1[3] + ((fac*cp2[3])>>8); + if(temp>254) cp[3]= 255; else cp[3]= temp; + + return col; +} + +static unsigned int mcol_sub(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int temp; + unsigned int col=0; + + if(fac==0) return col1; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + cp[0]= 255; + temp= cp1[1] - ((fac*cp2[1])>>8); + if(temp<0) cp[1]= 0; else cp[1]= temp; + temp= cp1[2] - ((fac*cp2[2])>>8); + if(temp<0) cp[2]= 0; else cp[2]= temp; + temp= cp1[3] - ((fac*cp2[3])>>8); + if(temp<0) cp[3]= 0; else cp[3]= temp; + + return col; +} + +static unsigned int mcol_mul(unsigned int col1, unsigned int col2, int fac) +{ + char *cp1, *cp2, *cp; + int mfac; + unsigned int col=0; + + if(fac==0) return col1; + + mfac= 255-fac; + + cp1= (char *)&col1; + cp2= (char *)&col2; + cp= (char *)&col; + + /* eerstmullen, dan fac blenden */ + cp[0]= 255; + cp[1]= (mfac*cp1[1] + fac*((cp2[1]*cp1[1])>>8) )>>8; + cp[2]= (mfac*cp1[2] + fac*((cp2[2]*cp1[2])>>8) )>>8; + cp[3]= (mfac*cp1[3] + fac*((cp2[3]*cp1[3])>>8) )>>8; + + + return col; +} + +static void vpaint_blend( unsigned int *col, unsigned int paintcol, int alpha) +{ + + if(Gvp.mode==VP_MIX || Gvp.mode==VP_FILT) *col= mcol_blend( *col, paintcol, alpha); + else if(Gvp.mode==VP_ADD) *col= mcol_add( *col, paintcol, alpha); + else if(Gvp.mode==VP_SUB) *col= mcol_sub( *col, paintcol, alpha); + else if(Gvp.mode==VP_MUL) *col= mcol_mul( *col, paintcol, alpha); +} + + +static int sample_backbuf_area(int x, int y) +{ + unsigned int rect[129*129], *rt; + int x1, y1, x2, y2, size, a, tot=0, index; + + if(totvpaintundo>=MAXINDEX) return 0; + + if(Gvp.size>64.0) Gvp.size= 64.0; + + x1= x-Gvp.size; + x2= x+Gvp.size; + CLAMP(x1, 0, curarea->winx); + CLAMP(x2, 0, curarea->winx); + y1= y-Gvp.size; + y2= y+Gvp.size; + CLAMP(y1, 0, curarea->winy); + CLAMP(y2, 0, curarea->winy); + + glReadPixels(x1+curarea->winrct.xmin, y1+curarea->winrct.ymin, x2-x1+1, y2-y1+1, GL_RGBA, GL_UNSIGNED_BYTE, rect); + if(G.order==B_ENDIAN) IMB_convert_rgba_to_abgr( (int)(4*Gvp.size*Gvp.size), rect); + + rt= rect; + size= (y2-y1)*(x2-x1); + if(size<=0) return 0; + + memset(indexar, 0, 2*totvpaintundo+2); /* plus 2! first element is total */ + + while(size--) { + + if(*rt) { + index= framebuffer_to_index(*rt); + if(index>0 && index<=totvpaintundo) + indexar[index] = 1; + } + + rt++; + } + + for(a=1; a<=totvpaintundo; a++) { + if(indexar[a]) indexar[tot++]= a; + } + + return tot; +} + +static unsigned int sample_backbuf(int x, int y) +{ + unsigned int col; + + if(x>=curarea->winx || y>=curarea->winy) return 0; + + x+= curarea->winrct.xmin; + y+= curarea->winrct.ymin; + + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + if(G.order==B_ENDIAN) SWITCH_INT(col); + + return framebuffer_to_index(col); +} + +static int calc_vp_alpha(MVert *mvert, short *mval) +{ + float fac, dx, dy, nor[3]; + int alpha; + short vertco[2]; + + if(Gvp.flag & VP_SOFT) { + project_short_noclip(mvert->co , vertco); + dx= mval[0]-vertco[0]; + dy= mval[1]-vertco[1]; + + fac= sqrt(dx*dx + dy*dy); + if(fac > Gvp.size) return 0; + + alpha= 255.0*Gvp.a*(1.0-fac/Gvp.size); + } + else { + alpha= 255.0*Gvp.a; + } + if(Gvp.flag & VP_NORMALS) { + VECCOPY(nor, mvert->no); + + /* transpose ! */ + fac= vpimat[2][0]*nor[0]+vpimat[2][1]*nor[1]+vpimat[2][2]*nor[2]; + if(fac>0.0) { + dx= vpimat[0][0]*nor[0]+vpimat[0][1]*nor[1]+vpimat[0][2]*nor[2]; + dy= vpimat[1][0]*nor[0]+vpimat[1][1]*nor[1]+vpimat[1][2]*nor[2]; + + alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac); + } + else return 0; + } + + return alpha; + +} + +int calc_vp_alpha_dl(DispList *disp, MVert *mvert, int vert, short *mval) +/* Lets us do soft vertex painting onto a deformed mesh */ +{ + float fac, dx, dy, nor[3]; + int alpha; + short vertco[2]; + + /* For safety's sake !*/ + if (!disp || !disp->verts || !disp->nors) + return calc_vp_alpha (mvert+vert, mval); + +// make display list + if(Gvp.flag & VP_SOFT) { + project_short_noclip(disp->verts+(vert*3), vertco); + dx= mval[0]-vertco[0]; + dy= mval[1]-vertco[1]; + + fac= sqrt(dx*dx + dy*dy); + if(fac > Gvp.size) return 0; + + alpha= 255.0*Gvp.a*(1.0-fac/Gvp.size); + } + else { + alpha= 255.0*Gvp.a; + } + + if(Gvp.flag & VP_NORMALS) { + + VECCOPY(nor, disp->nors+(vert*3)); + +// transpose ! + fac= vpimat[2][0]*nor[0]+vpimat[2][1]*nor[1]+vpimat[2][2]*nor[2]; + if(fac>0.0) { + dx= vpimat[0][0]*nor[0]+vpimat[0][1]*nor[1]+vpimat[0][2]*nor[2]; + dy= vpimat[1][0]*nor[0]+vpimat[1][1]*nor[1]+vpimat[1][2]*nor[2]; + + alpha*= fac/sqrt(dx*dx + dy*dy + fac*fac); + } + else return 0; + } + + return alpha; + +} + + +void wpaint_undo (void){ + Mesh *me; + + me = get_mesh(OBACT); + if (!me) + return; + + if (!wpaintundobuf) + return; + + if (!me->dvert) + return; + + if (totwpaintundo != me->totvert) + return; + + free_dverts(me->dvert, me->totvert); + + me->dvert= MEM_mallocN(sizeof(MDeformVert)*me->totvert, "deformVert"); + copy_dverts(me->dvert, wpaintundobuf, totwpaintundo); + + makeDispList(OBACT); + scrarea_do_windraw(curarea); + +}; + +void copy_wpaint_undo (MDeformVert *dverts, int dcount){ + if (wpaintundobuf) + free_dverts(wpaintundobuf, totwpaintundo); + + wpaintundobuf = MEM_mallocN (sizeof(MDeformVert)*dcount, "wpaintundo"); + totwpaintundo = dcount; + copy_dverts (wpaintundobuf, dverts, dcount); +}; + +void weight_paint(void) +{ + Object *ob; + Mesh *me; + MFace *mface; + TFace *tface; + float mat[4][4], imat[4][4]; + int index, totindex; + short mval[2], mvalo[2], firsttime=1; + MDeformWeight *dw, *uw; + extern float editbutvweight; + DispList *dl; + + + if((G.f & G_WEIGHTPAINT)==0) return; + if(G.obedit) return; + if(G.obpose) return; + + if(indexar==0) init_vertexpaint(); + + ob= OBACT; + me= get_mesh(ob); + if (!me->dvert){ + return; + } + if(me==0 || me->totface==0) return; + if(ob->lay & G.vd->lay); else error("Active object not in this layer!"); + +// if(me->tface==NULL && me->mcol==NULL) make_vertexcol(); + +// if(me->tface==NULL && me->mcol==NULL) return; + + /* imat voor normalen */ + Mat4MulMat4(mat, ob->obmat, G.vd->viewmat); + Mat4Invert(imat, mat); + Mat3CpyMat4(vpimat, imat); + + /* projektiematrix laden */ + mymultmatrix(ob->obmat); + mygetsingmatrix(mat); + myloadmatrix(G.vd->viewmat); + + getmouseco_areawin(mvalo); + + if(me->tface) tface_to_mcol(me); + copy_vpaint_undo( (unsigned int *)me->mcol, me->totface); + copy_wpaint_undo(me->dvert, me->totvert); + + getmouseco_areawin(mval); + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + while (get_mbut() & L_MOUSE) { + getmouseco_areawin(mval); + + if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { + + if(firsttime) draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0); + else draw_sel_circle(mval, mvalo, Gvp.size, Gvp.size, 0); + + firsttime= 0; + + /* welke vlakken doen mee */ + if(Gvp.flag & VP_AREA) { + totindex= sample_backbuf_area(mval[0], mval[1]); + } + else { + indexar[0]= sample_backbuf(mval[0], mval[1]); + if(indexar[0]) totindex= 1; + else totindex= 0; + } + + MTC_Mat4SwapMat4(G.vd->persmat, mat); + + if(Gvp.flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + + mface= ((MFace *)me->mface) + (indexar[index]-1); + + if(mface->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } + } + + if((G.f & G_FACESELECT) && me->tface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + + tface= ((TFace *)me->tface) + (indexar[index]-1); + + if((tface->flag & TF_SELECT)==0) { + indexar[index]= 0; + } + } + } + } + + dl= find_displist(&ob->disp, DL_VERTS); + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totface) { + mface= ((MFace *)me->mface) + (indexar[index]-1); + + + if (calc_vp_alpha_dl(dl, me->mvert, mface->v1, mval)){ + dw= verify_defweight(me->dvert+mface->v1, ob->actdef-1); + uw= verify_defweight(wpaintundobuf+mface->v1, ob->actdef-1); + if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a)); + } + + if (calc_vp_alpha_dl(dl, me->mvert, mface->v2, mval)){ + dw= verify_defweight(me->dvert+mface->v2, ob->actdef-1); + uw= verify_defweight(wpaintundobuf+mface->v2, ob->actdef-1); + if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a)); + } + + if (calc_vp_alpha_dl(dl, me->mvert, mface->v3, mval)){ + dw= verify_defweight(me->dvert+mface->v3, ob->actdef-1); + uw= verify_defweight(wpaintundobuf+mface->v3, ob->actdef-1); + if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a)); + } + + if(mface->v4) { + if (calc_vp_alpha_dl(dl, me->mvert, mface->v4, mval)){ + dw= verify_defweight(me->dvert+mface->v4, ob->actdef-1); + uw= verify_defweight(wpaintundobuf+mface->v4, ob->actdef-1); + if (dw) dw->weight = editbutvweight*Gvp.a + (uw->weight*(1.0-Gvp.a)); + } + } + } + } + + MTC_Mat4SwapMat4(G.vd->persmat, mat); + + } + else BIF_wait_for_statechange(); + + if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { +// makeDispList(ob); + scrarea_do_windraw(curarea); + screen_swapbuffers(); + backdrawview3d(0); + draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0); + + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + } + } + + if(me->tface) { + MEM_freeN(me->mcol); + me->mcol= 0; + } + + /* cirkel wissen */ + draw_sel_circle(0, mvalo, 0, Gvp.size, 1); + + makeDispList(ob); + + allqueue(REDRAWVIEW3D, 0); + +} + +void vertex_paint() +{ + Object *ob; + Mesh *me; + MFace *mface; + TFace *tface; + float mat[4][4], imat[4][4]; + unsigned int paintcol=0, *mcol, fcol1, fcol2; + int index, alpha, totindex, total; + short mval[2], mvalo[2], firsttime=1; + + if((G.f & G_VERTEXPAINT)==0) return; + if(G.obedit) return; + + if(indexar==0) init_vertexpaint(); + + ob= OBACT; + me= get_mesh(ob); + if(me==0 || me->totface==0) return; + if(ob->lay & G.vd->lay); else error("Active object not in this layer!"); + + if(me->tface==NULL && me->mcol==NULL) make_vertexcol(); + + if(me->tface==NULL && me->mcol==NULL) return; + + /* imat voor normalen */ + Mat4MulMat4(mat, ob->obmat, G.vd->viewmat); + Mat4Invert(imat, mat); + Mat3CpyMat4(vpimat, imat); + + /* projektiematrix laden */ + mymultmatrix(ob->obmat); + mygetsingmatrix(mat); + myloadmatrix(G.vd->viewmat); + + paintcol= vpaint_get_current_col(); + + getmouseco_areawin(mvalo); + + if(me->tface) tface_to_mcol(me); + copy_vpaint_undo( (unsigned int *)me->mcol, me->totface); + + getmouseco_areawin(mval); + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + + while (get_mbut() & L_MOUSE) { + getmouseco_areawin(mval); + + if(firsttime || mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { + + if(firsttime) draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0); + else draw_sel_circle(mval, mvalo, Gvp.size, Gvp.size, 0); + + firsttime= 0; + + /* welke vlakken doen mee */ + if(Gvp.flag & VP_AREA) { + totindex= sample_backbuf_area(mval[0], mval[1]); + } + else { + indexar[0]= sample_backbuf(mval[0], mval[1]); + if(indexar[0]) totindex= 1; + else totindex= 0; + } + + MTC_Mat4SwapMat4(G.vd->persmat, mat); + + if(Gvp.flag & VP_COLINDEX) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + + mface= ((MFace *)me->mface) + (indexar[index]-1); + + if(mface->mat_nr!=ob->actcol-1) { + indexar[index]= 0; + } + } + } + } + if((G.f & G_FACESELECT) && me->tface) { + for(index=0; index<totindex; index++) { + if(indexar[index] && indexar[index]<=me->totface) { + + tface= ((TFace *)me->tface) + (indexar[index]-1); + + if((tface->flag & TF_SELECT)==0) { + indexar[index]= 0; + } + } + } + } + + for(index=0; index<totindex; index++) { + + if(indexar[index] && indexar[index]<=me->totface) { + + mface= ((MFace *)me->mface) + (indexar[index]-1); + mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1); + + if(Gvp.mode==VP_FILT) { + fcol1= mcol_blend( mcol[0], mcol[1], 128); + if(mface->v4) { + fcol2= mcol_blend( mcol[2], mcol[3], 128); + paintcol= mcol_blend( fcol1, fcol2, 128); + } + else { + paintcol= mcol_blend( mcol[2], fcol1, 170); + } + + } + + total= 0; + + total+= alpha= calc_vp_alpha(me->mvert+mface->v1, mval); + if(alpha) vpaint_blend( mcol, paintcol, alpha); + + total+= alpha= calc_vp_alpha(me->mvert+mface->v2, mval); + if(alpha) vpaint_blend( mcol+1, paintcol, alpha); + + total+= alpha= calc_vp_alpha(me->mvert+mface->v3, mval); + if(alpha) vpaint_blend( mcol+2, paintcol, alpha); + + if(mface->v4) { + total+= alpha= calc_vp_alpha(me->mvert+mface->v4, mval); + if(alpha) vpaint_blend( mcol+3, paintcol, alpha); + } + + /* if(total==0) { */ + /* alpha= 25*Gvp.a; */ + /* vpaint_blend( mcol, paintcol, alpha); */ + /* vpaint_blend( mcol+1, paintcol, alpha); */ + /* vpaint_blend( mcol+2, paintcol, alpha); */ + /* if(mface->v4) vpaint_blend( mcol+3, paintcol, alpha); */ + /* } */ + } + } + + MTC_Mat4SwapMat4(G.vd->persmat, mat); + + } + else BIF_wait_for_statechange(); + + if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { + do_shared_vertexcol(me); + if(me->tface) { + mcol_to_tface(me, 0); + } + + scrarea_do_windraw(curarea); + screen_swapbuffers(); + backdrawview3d(0); + draw_sel_circle(mval, 0, Gvp.size, Gvp.size, 0); + + mvalo[0]= mval[0]; + mvalo[1]= mval[1]; + } + } + + if(me->tface) { + MEM_freeN(me->mcol); + me->mcol= 0; + } + + /* cirkel wissen */ + draw_sel_circle(0, mvalo, 0, Gvp.size, 1); + + allqueue(REDRAWVIEW3D, 0); +} + +void set_wpaint(void) /* toggle */ +{ + Object *ob; + Mesh *me; + + scrarea_queue_headredraw(curarea); + ob= OBACT; + me= get_mesh(ob); + + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_WEIGHTPAINT; + return; + } + +// if(me && me->tface==NULL && me->mcol==NULL) make_vertexcol(); + + if(G.f & G_WEIGHTPAINT) G.f &= ~G_WEIGHTPAINT; + else G.f |= G_WEIGHTPAINT; + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWBUTSGAME, 0); + + if(G.f & G_WEIGHTPAINT) { + setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT); + } + else { + freefastshade(); /* voor zekerheid */ + if (ob) + makeDispList(ob); + if(!(G.f & G_FACESELECT)) + setcursor_space(SPACE_VIEW3D, CURSOR_STD); + } +} + + +void set_vpaint(void) /* toggle */ +{ + Object *ob; + Mesh *me; + + scrarea_queue_headredraw(curarea); + ob= OBACT; + me= get_mesh(ob); + + if(me && me->totface>=MAXINDEX) { + error("Maximum number of faces: %d", MAXINDEX-1); + G.f &= ~G_VERTEXPAINT; + return; + } + + if(me && me->tface==NULL && me->mcol==NULL) make_vertexcol(); + + if(G.f & G_VERTEXPAINT){ + G.f &= ~G_VERTEXPAINT; + } + else { + G.f |= G_VERTEXPAINT; + /* Turn off weight painting */ + if (G.f & G_WEIGHTPAINT) + set_wpaint(); + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWBUTSGAME, 0); + + if(G.f & G_VERTEXPAINT) { + setcursor_space(SPACE_VIEW3D, CURSOR_VPAINT); + } + else { + freefastshade(); /* voor zekerheid */ + if (ob) makeDispList(ob); + if((G.f & G_FACESELECT)==0) setcursor_space(SPACE_VIEW3D, CURSOR_STD); + } +} + |