diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2012-01-22 21:54:23 +0400 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2012-01-22 21:54:23 +0400 |
commit | 1a93d8834319b890ff0cbc70231b14635603ae95 (patch) | |
tree | 87ee1ecd503872e91116566db9df4730b3ebccbe /source/blender/blenkernel/intern | |
parent | df51fd74cf826c42a90212082abb27e99484257a (diff) |
Add weight preview to WeightVG modifiers, and first, simple/basic refactor of how modifiers can generate preview.
User side:
* Preview for DynamicPaint should keep the same behavior (for now). Weight preview should be somawhat quicker, though.
* Preview for WeightVG modifiers is only active in WeightPaint mode, and if the affected vgroup is the active one.
* Last active preview modifier in stack wins!
Note: that modifier preview topic is yet to be further refined, quite raw/incomplete for now.
Dev side:
* In draw code, renamed DRAW_DYNAMIC_PAINT_PREVIEW flag to DRAW_MODIFIERS_PREVIEW
* Removed use of MOD_DPAINT_PREVIEW_READY in DynamicPaint code (seems unecessary, and if it was, should be of more general scope).
* Added eModifierTypeFlag_UsesPreview to ModifierTypeFlag, for modifiers that can generate some preview data.
* Added three new modifier funcs, to handle preview modifiers in draw code / mod stack.
* For weights preview: added the generic DM_update_weight_mcol func, which can update WEIGHT_MCOL layer with either a given array of weights (currently used by DynamicPaint only), or from current active vgroup(s).
So now, draw code is fully generic (i.e. no more modifier-type checking in it). Mod stack code is generic to some extent, but will need more work.
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 164 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/dynamicpaint.c | 26 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 42 |
3 files changed, 164 insertions, 68 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b670a360a6a..27aeeb95903 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -722,24 +722,23 @@ void vDM_ColorBand_store(ColorBand *coba) * note that we could save some memory and allocate RGB only but then we'd need to * re-arrange the colors when copying to the face since MCol has odd ordering, * so leave this as is - campbell */ -static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_flag, ColorBand *coba) +static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba) { - Mesh *me = ob->data; - unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * me->totvert * 4, "weightmap_v"); + MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT); + int numVerts = dm->getNumVerts(dm); + unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * numVerts * 4, "weightmap_v"); - if (me->dvert) { + if (dv) { unsigned char *wc = wtcol_v; - MDeformVert *dv= me->dvert; unsigned int i; - /* varisbles for multipaint */ + /* variables for multipaint */ const int defbase_tot = BLI_countlist(&ob->defbase); const int defbase_act = ob->actdef-1; char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__); const int selected = get_selected_defgroups(ob, dg_flags, defbase_tot); - /* const int unselected = defbase_tot - selected; */ /* UNUSED */ - for (i = me->totvert; i != 0; i--, wc += 4, dv++) { + for (i = numVerts; i != 0; i--, wc += 4, dv++) { calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, dg_flags, selected, draw_flag); } @@ -748,48 +747,94 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_fla else { int col_i; weightpaint_color((unsigned char *)&col_i, coba, 0.0f); - fill_vn_i((int *)wtcol_v, me->totvert, col_i); + fill_vn_i((int *)wtcol_v, numVerts, col_i); } return wtcol_v; } -static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) +/* return an array of vertex weight colors from given weights, caller must free. + * + * note that we could save some memory and allocate RGB only but then we'd need to + * re-arrange the colors when copying to the face since MCol has odd ordering, + * so leave this as is - campbell */ +static unsigned char *calc_colors_from_weights_array(const int num, float *weights) { - ColorBand *coba= stored_cb; /* warning, not a local var */ + unsigned char *wtcol_v = MEM_mallocN(sizeof(unsigned char) * num * 4, "weightmap_v"); + unsigned char *wc = wtcol_v; + int i; - Mesh *me = ob->data; - unsigned char *wtcol_v = calc_weightpaint_vert_array(ob, draw_flag, coba); - unsigned char *wtcol_f = MEM_mallocN (sizeof(unsigned char) * me->totface*4*4, "weightmap_f"); - unsigned char *wtcol_f_step = wtcol_f; + for (i = 0; i < num; i++, wc += 4, weights++) + weightpaint_color((unsigned char *) wc, NULL, *weights); + + return wtcol_v; +} - MFace *mf = me->mface; +void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, + float *weights, int num, const int *indices) +{ + ColorBand *coba= stored_cb; /* warning, not a local var */ + + MFace *mf = dm->getFaceArray(dm); + int numFaces = dm->getNumFaces(dm); + int numVerts = dm->getNumVerts(dm); + unsigned char *wtcol_v; + unsigned char *wtcol_f = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL); int i; - for (i=0; i<me->totface; i++, mf++, wtcol_f_step += (4 * 4)) { + /* If no CD_WEIGHT_MCOL existed yet, add a new one! */ + if (!wtcol_f) + wtcol_f = CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces); + + if (wtcol_f) { + unsigned char *wtcol_f_step = wtcol_f; + + /* Weights are given by caller. */ + if (weights) { + float *w = weights; + /* If indices is not NULL, it means we do not have weights for all vertices, + * so we must create them (and set them to zero)... */ + if(indices) { + w = MEM_callocN(sizeof(float)*numVerts, "Temp weight array DM_update_weight_mcol"); + i = num; + while(i--) + w[indices[i]] = weights[i]; + } + + /* Convert float weights to colors. */ + wtcol_v = calc_colors_from_weights_array(numVerts, w); + + if(indices) + MEM_freeN(w); + } + + /* No weights given, take them from active vgroup(s). */ + else + wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + + /* Now copy colors in all face verts. */ + for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) { #if 0 - unsigned int fidx= mf->v4 ? 3:2; + unsigned int fidx= mf->v4 ? 3:2; #else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */ - unsigned int fidx; - if (mf->v4) { - fidx = 3; - } - else { - fidx = 2; - *(int *)(&wtcol_f_step[3 * 4]) = 0; - } + unsigned int fidx; + if (mf->v4) { + fidx = 3; + } + else { + fidx = 2; + *(int *)(&wtcol_f_step[3 * 4]) = 0; + } #endif - do { - copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], - (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); - } while (fidx--); + do { + copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], + (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); + } while (fidx--); + } + MEM_freeN(wtcol_v); } - - MEM_freeN(wtcol_v); - - CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol_f, dm->numFaceData); } /* new value for useDeform -1 (hack for the gameengine): @@ -803,7 +848,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos int needMapping, CustomDataMask dataMask, int index, int useCache) { Mesh *me = ob->data; - ModifierData *firstmd, *md; + ModifierData *firstmd, *md, *previewmd = NULL; LinkNode *datamasks, *curr; CustomDataMask mask, nextmask, append_mask = 0; float (*deformedVerts)[3] = NULL; @@ -816,8 +861,17 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos int has_multires = mmd != NULL, multires_applied = 0; int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; - int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | - (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); + const int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | + (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); + /* Generic preview only in object mode! */ + const int do_mod_mcol = (ob->mode == OB_MODE_OBJECT); +#if 0 /* XXX Will re-enable this when we have global mod stack options. */ + const int do_final_wmcol = (scene->toolsettings->weights_preview == WP_WPREVIEW_FINAL) && do_wmcol; +#endif + const int do_final_wmcol = FALSE; + int do_init_wmcol = ((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol); + /* XXX Same as above... For now, only weights preview in WPaint mode. */ + const int do_mod_wmcol = do_init_wmcol; if(mmd && !mmd->sculptlvl) has_multires = 0; @@ -842,6 +896,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); curr = datamasks; + if(do_mod_wmcol || do_mod_mcol) { + /* Find the last active modifier generating a preview, or NULL if none. */ + /* XXX Currently, DPaint modifier just ignores this. + * Needs a stupid hack... + * The whole "modifier preview" thing has to be (re?)designed, anyway! */ + previewmd = modifiers_getLastPreview(scene, md, required_mode); + } + if(deform_r) *deform_r = NULL; *final_r = NULL; @@ -997,8 +1059,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos CDDM_calc_normals(dm); } - if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, dm, draw_flag); + if(do_init_wmcol) + DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); /* Constructive modifiers need to have an origindex * otherwise they wont have anywhere to copy the data from. @@ -1085,8 +1147,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } /* in case of dynamic paint, make sure preview mask remains for following modifiers */ + /* XXX Temp and hackish solution! */ if (md->type == eModifierType_DynamicPaint) append_mask |= CD_MASK_WEIGHT_MCOL; + /* In case of active preview modifier, make sure preview mask remains for following modifiers. */ + else if ((md == previewmd) && (do_mod_wmcol)) { + DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL); + append_mask |= CD_MASK_WEIGHT_MCOL; + } } isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform); @@ -1114,10 +1182,19 @@ 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) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, finaldm, draw_flag); +#if 0 /* For later nice mod preview! */ + /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */ + if(do_final_wmcol) + DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); +#endif } else if(dm) { finaldm = dm; + +#if 0 /* For later nice mod preview! */ + /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */ + if(do_final_wmcol) + DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); +#endif } else { finaldm = CDDM_from_mesh(me, ob); @@ -1126,8 +1203,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos CDDM_calc_normals(finaldm); } - if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) - add_weight_mcol_dm(ob, finaldm, draw_flag); + /* In this case, we should never have weight-modifying modifiers in stack... */ + if(do_init_wmcol) + DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL); } /* add an orco layer if needed */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 6a2207d455c..18c8d0f0106 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1574,7 +1574,6 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData DynamicPaintSurface *surface = pmd->canvas->surfaces.first; int update_normals = 0; - pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY; /* loop through surfaces */ for (; surface; surface=surface->next) { @@ -1651,7 +1650,6 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData } } } - pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY; } } @@ -1711,29 +1709,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData if (surface->flags & MOD_DPAINT_PREVIEW) { /* Save preview results to weight layer, to be * able to share same drawing methods */ - MFace *mface = result->getFaceArray(result); - int numOfFaces = result->getNumFaces(result); - int i; - MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL); - if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces); - - if (col) { - #pragma omp parallel for schedule(static) - for (i=0; i<numOfFaces; i++) { - float temp_color[3]; - int j = (mface[i].v4) ? 4 : 3; - while (j--) { - int index = *((&mface[i].v1)+j); - - weight_to_rgb(temp_color, weight[index]); - col[i*4+j].r = FTOCHAR(temp_color[2]); - col[i*4+j].g = FTOCHAR(temp_color[1]); - col[i*4+j].b = FTOCHAR(temp_color[0]); - col[i*4+j].a = 255; - } - } - pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY; - } + DM_update_weight_mcol(ob, result, 0, weight, 0, NULL); } /* apply weights into a vertex group, if doesnt exists add a new layer */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 5a389019519..911d303b4cf 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -142,6 +142,19 @@ int modifier_supportsMapping(ModifierData *md) (mti->flags & eModifierTypeFlag_SupportsMapping)); } +int modifier_isPreview(ModifierData *md) +{ + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (!(mti->flags & eModifierTypeFlag_UsesPreview)) + return FALSE; + + if (md->mode & eModifierMode_Realtime) + return TRUE; + + return FALSE; +} + ModifierData *modifiers_findByType(Object *ob, ModifierType type) { ModifierData *md = ob->modifiers.first; @@ -385,6 +398,21 @@ LinkNode *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData return dataMasks; } +ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode) +{ + ModifierData *tmp_md = NULL; + + if (required_mode != eModifierMode_Realtime) + return tmp_md; + + /* Find the latest modifier in stack generating preview. */ + for(; md; md = md->next) { + if(modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md)) + tmp_md = md; + } + return tmp_md; +} + ModifierData *modifiers_getVirtualModifierList(Object *ob) { /* Kinda hacky, but should be fine since we are never @@ -545,6 +573,20 @@ int modifiers_isCorrectableDeformed(Object *ob) return 0; } +/* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer + * to preview something... Used by DynamicPaint and WeightVG currently. */ +int modifiers_isPreview(Object *ob) +{ + ModifierData *md = ob->modifiers.first; + + for (; md; md = md->next) { + if (modifier_isPreview(md)) + return TRUE; + } + + return FALSE; +} + int modifiers_indexInObject(Object *ob, ModifierData *md_seek) { int i= 0; |