2.5: weight paint mode fix for corrupted layer data, and added

a customdata layer specifically to store weightpaint colors
instead of abusing the vertex colors layers.
This commit is contained in:
Brecht Van Lommel 2009-04-02 14:38:40 +00:00
parent 4bb41c3dcd
commit e9ad9f894e
5 changed files with 123 additions and 135 deletions

View File

@ -1433,6 +1433,8 @@ static float *get_editmesh_orco_verts(EditMesh *em)
return orco;
}
/* orco custom data layer */
static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
{
DerivedMesh *dm;
@ -1484,6 +1486,96 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
}
/* weight paint colors */
/* Something of a hack, at the moment deal with weightpaint
* by tucking into colors during modifier eval, only in
* wpaint mode. Works ok but need to make sure recalc
* happens on enter/exit wpaint.
*/
void weight_to_rgb(float input, float *fr, float *fg, float *fb)
{
float blend;
blend= ((input/2.0f)+0.5f);
if (input<=0.25f){ // blue->cyan
*fr= 0.0f;
*fg= blend*input*4.0f;
*fb= blend;
}
else if (input<=0.50f){ // cyan->green
*fr= 0.0f;
*fg= blend;
*fb= blend*(1.0f-((input-0.25f)*4.0f));
}
else if (input<=0.75){ // green->yellow
*fr= blend * ((input-0.50f)*4.0f);
*fg= blend;
*fb= 0.0f;
}
else if (input<=1.0){ // yellow->red
*fr= blend;
*fg= blend * (1.0f-((input-0.75f)*4.0f));
*fb= 0.0f;
}
}
static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
{
Mesh *me = ob->data;
float colf[4], input = 0.0f;
int i;
if (me->dvert) {
for (i=0; i<me->dvert[vert].totweight; i++)
if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
input+=me->dvert[vert].dw[i].weight;
}
CLAMP(input, 0.0f, 1.0f);
if(coba)
do_colorband(coba, input, colf);
else
weight_to_rgb(input, colf, colf+1, colf+2);
col[3] = (unsigned char)(colf[0] * 255.0f);
col[2] = (unsigned char)(colf[1] * 255.0f);
col[1] = (unsigned char)(colf[2] * 255.0f);
col[0] = 255;
}
static ColorBand *stored_cb= NULL;
void vDM_ColorBand_store(ColorBand *coba)
{
stored_cb= coba;
}
static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
{
Mesh *me = ob->data;
MFace *mf = me->mface;
ColorBand *coba= stored_cb; /* warning, not a local var */
unsigned char *wtcol;
int i;
wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
for (i=0; i<me->totface; i++, mf++) {
calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]);
calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]);
calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]);
if (mf->v4)
calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]);
}
CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
}
static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
DerivedMesh **deform_r, DerivedMesh **final_r,
int useRenderParams, int useDeform,
@ -1547,6 +1639,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
*/
if (deform_r) {
*deform_r = CDDM_from_mesh(me, ob);
if(deformedVerts) {
CDDM_apply_vert_coords(*deform_r, deformedVerts);
CDDM_calc_normals(*deform_r);
@ -1632,6 +1725,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
CDDM_apply_vert_coords(dm, deformedVerts);
CDDM_calc_normals(dm);
}
if(dataMask & CD_MASK_WEIGHT_MCOL)
add_weight_mcol_dm(ob, dm);
}
/* create an orco derivedmesh in parallel */
@ -1695,14 +1791,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
CDDM_apply_vert_coords(finaldm, deformedVerts);
CDDM_calc_normals(finaldm);
if(dataMask & CD_MASK_WEIGHT_MCOL)
add_weight_mcol_dm(ob, finaldm);
} else if(dm) {
finaldm = dm;
} else {
finaldm = CDDM_from_mesh(me, ob);
if(deformedVerts) {
CDDM_apply_vert_coords(finaldm, deformedVerts);
CDDM_calc_normals(finaldm);
}
if(dataMask & CD_MASK_WEIGHT_MCOL)
add_weight_mcol_dm(ob, finaldm);
}
/* add an orco layer if needed */
@ -1932,96 +2035,6 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
MEM_freeN(deformedVerts);
}
/***/
/* Something of a hack, at the moment deal with weightpaint
* by tucking into colors during modifier eval, only in
* wpaint mode. Works ok but need to make sure recalc
* happens on enter/exit wpaint.
*/
void weight_to_rgb(float input, float *fr, float *fg, float *fb)
{
float blend;
blend= ((input/2.0f)+0.5f);
if (input<=0.25f){ // blue->cyan
*fr= 0.0f;
*fg= blend*input*4.0f;
*fb= blend;
}
else if (input<=0.50f){ // cyan->green
*fr= 0.0f;
*fg= blend;
*fb= blend*(1.0f-((input-0.25f)*4.0f));
}
else if (input<=0.75){ // green->yellow
*fr= blend * ((input-0.50f)*4.0f);
*fg= blend;
*fb= 0.0f;
}
else if (input<=1.0){ // yellow->red
*fr= blend;
*fg= blend * (1.0f-((input-0.75f)*4.0f));
*fb= 0.0f;
}
}
static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
{
Mesh *me = ob->data;
float colf[4], input = 0.0f;
int i;
if (me->dvert) {
for (i=0; i<me->dvert[vert].totweight; i++)
if (me->dvert[vert].dw[i].def_nr==ob->actdef-1)
input+=me->dvert[vert].dw[i].weight;
}
CLAMP(input, 0.0f, 1.0f);
if(coba)
do_colorband(coba, input, colf);
else
weight_to_rgb(input, colf, colf+1, colf+2);
col[3] = (unsigned char)(colf[0] * 255.0f);
col[2] = (unsigned char)(colf[1] * 255.0f);
col[1] = (unsigned char)(colf[2] * 255.0f);
col[0] = 255;
}
static ColorBand *stored_cb= NULL;
void vDM_ColorBand_store(ColorBand *coba)
{
stored_cb= coba;
}
static unsigned char *calc_weightpaint_colors(Object *ob)
{
Mesh *me = ob->data;
MFace *mf = me->mface;
ColorBand *coba= stored_cb; /* warning, not a local var */
unsigned char *wtcol;
int i;
wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
for (i=0; i<me->totface; i++, mf++) {
calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]);
calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]);
calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]);
if (mf->v4)
calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]);
}
return wtcol;
}
static void clear_mesh_caches(Object *ob)
{
Mesh *me= ob->data;
@ -2052,42 +2065,16 @@ static void clear_mesh_caches(Object *ob)
static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
{
Mesh *me = ob->data;
float min[3], max[3];
//int needMapping= 0;
Object *obact = scene->basact?scene->basact->object:NULL;
int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT);
int needMapping = editing && (ob==obact);
float min[3], max[3];
clear_mesh_caches(ob);
if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
// if(dataMask & CD_MASK_WEIGHTPAINT) {
MCol *wpcol = (MCol*)calc_weightpaint_colors(ob);
int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL);
int prevactive = CustomData_get_active_layer(&me->fdata, CD_MCOL);
int prevrender = CustomData_get_render_layer(&me->fdata, CD_MCOL);
/* ugly hack here, we temporarily add a new active mcol layer with
weightpaint colors in it, that is then duplicated in CDDM_from_mesh */
CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, wpcol, me->totface);
CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
CustomData_set_layer_render(&me->fdata, CD_MCOL, layernum);
mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
&ob->derivedFinal, 0, 1,
needMapping, dataMask, -1);
CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface);
CustomData_set_layer_active(&me->fdata, CD_MCOL, prevactive);
CustomData_set_layer_render(&me->fdata, CD_MCOL, prevrender);
}
else {
mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
&ob->derivedFinal, G.rendering, 1,
needMapping, dataMask, -1);
}
mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
&ob->derivedFinal, 0, 1,
needMapping, dataMask, -1);
INIT_MINMAX(min, max);

View File

@ -482,10 +482,14 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
MVert *mv = cddm->mvert;
MFace *mf = cddm->mface;
MCol *mc = DM_get_face_data_layer(dm, CD_MCOL);
MCol *mc;
float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
if(!mc)
mc = DM_get_face_data_layer(dm, CD_MCOL);
for(i = 0; i < dm->numFaceData; i++, mf++) {
int drawSmooth = (mf->flag & ME_SMOOTH);
@ -926,13 +930,6 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *ob)
index = CustomData_get_layer(&dm->faceData, CD_ORIGINDEX);
for(i = 0; i < mesh->totface; ++i, ++index)
*index = i;
/* works in conjunction with hack during modifier calc, where active mcol
layer with weight paint colors is temporarily added */
/* XXX make this real but temporary layer */
// if ((G.f & G_WEIGHTPAINT) &&
// (ob && ob==(scene->basact?scene->basact->object:NULL)))
// CustomData_duplicate_referenced_layer(&dm->faceData, CD_MCOL);
return dm;
}

View File

@ -707,14 +707,16 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
{sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL}
layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL},
{sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol,
layerSwap_mcol, layerDefault_mcol},
};
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
"CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
"CDMloopCol", "CDTangent", "CDMDisps"};
"CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol"};
const CustomDataMask CD_MASK_BAREMESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
@ -728,7 +730,7 @@ const CustomDataMask CD_MASK_EDITMESH =
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT;
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL;
const CustomDataMask CD_MASK_BMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
const CustomDataMask CD_MASK_FACECORNERS =

View File

@ -1858,8 +1858,10 @@ static CustomDataMask get_viewedit_datamask(bScreen *screen)
}
/* check if we need mcols due to vertex paint or weightpaint */
if(G.f & G_VERTEXPAINT || G.f & G_WEIGHTPAINT)
if(G.f & G_VERTEXPAINT)
mask |= CD_MASK_MCOL;
if(G.f & G_WEIGHTPAINT)
mask |= CD_MASK_WEIGHT_MCOL;
if(G.f & G_SCULPTMODE)
mask |= CD_MASK_MDISPS;

View File

@ -75,9 +75,8 @@ typedef struct CustomData {
#define CD_MLOOPCOL 17
#define CD_TANGENT 18
#define CD_MDISPS 19
#define CD_NUMTYPES 20
/* fake type, derivedmesh wants CustomDataMask for weightpaint too, is not stored */
#define CD_WEIGHTPAINT 30
#define CD_WEIGHT_MCOL 20 /* for displaying weightpaint colors */
#define CD_NUMTYPES 21
/* Bits for CustomDataMask */
#define CD_MASK_MVERT (1 << CD_MVERT)
@ -100,6 +99,7 @@ typedef struct CustomData {
#define CD_MASK_MLOOPCOL (1 << CD_MLOOPCOL)
#define CD_MASK_TANGENT (1 << CD_TANGENT)
#define CD_MASK_MDISPS (1 << CD_MDISPS)
#define CD_MASK_WEIGHT_MCOL (1 << CD_WEIGHT_MCOL)
/* derivedmesh wants CustomDataMask for weightpaint too, is not customdata though */
#define CD_MASK_WEIGHTPAINT (1 << CD_WEIGHTPAINT)