/** * $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 #ifdef WIN32 #include #include "BLI_winstuff.h" #else #include #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; itotface*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; indextotface) { 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; indextotface) { 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; indextotface) { 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; indextotface) { 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; indextotface) { tface= ((TFace *)me->tface) + (indexar[index]-1); if((tface->flag & TF_SELECT)==0) { indexar[index]= 0; } } } } for(index=0; indextotface) { 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); } }