Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/paint_vertex.c
| Show First 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | if (dm) { | ||||
| if (me && me->mcol) { | if (me && me->mcol) { | ||||
| return (me->mcol == CustomData_get_layer(&dm->faceData, CD_MCOL)); | return (me->mcol == CustomData_get_layer(&dm->faceData, CD_MCOL)); | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* if the polygons from the mesh and the 'derivedFinal' match | |||||
| * we can assume that no modifiers are applied and that its worth adding tessellated faces | |||||
| * so 'vertex_paint_use_fast_update_check()' returns true */ | |||||
| static bool vertex_paint_use_tessface_check(Object *ob, Mesh *me) | |||||
| { | |||||
| DerivedMesh *dm = ob->derivedFinal; | |||||
| if (me && dm) { | |||||
| return (me->mpoly == CustomData_get_layer(&dm->polyData, CD_MPOLY)); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| static void update_tessface_data(Object *ob, Mesh *me) | |||||
| { | |||||
| if (vertex_paint_use_tessface_check(ob, me)) { | |||||
| /* assume if these exist, that they are up to date & valid */ | |||||
| if (!me->mcol || !me->mface) { | |||||
| /* should always be true */ | |||||
| /* XXX Why this clearing? tessface_calc will reset it anyway! */ | |||||
| #if 0 | |||||
| if (me->mcol) { | |||||
| memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface); | |||||
| } | |||||
| #endif | |||||
| /* create tessfaces because they will be used for drawing & fast updates */ | |||||
| BKE_mesh_tessface_calc(me); /* does own call to update pointers */ | |||||
| } | |||||
| } | |||||
| else { | |||||
| if (me->totface) { | |||||
| /* this wont be used, theres no need to keep it */ | |||||
| BKE_mesh_tessface_clear(me); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* polling - retrieve whether cursor should be set or operator should be done */ | /* polling - retrieve whether cursor should be set or operator should be done */ | ||||
| /* Returns true if vertex paint mode is active */ | /* Returns true if vertex paint mode is active */ | ||||
| int vertex_paint_mode_poll(bContext *C) | int vertex_paint_mode_poll(bContext *C) | ||||
| { | { | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly; | return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly; | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| Brush *brush = BKE_paint_brush(&vp->paint); | Brush *brush = BKE_paint_brush(&vp->paint); | ||||
| unsigned char col[4]; | unsigned char col[4]; | ||||
| rgb_float_to_uchar(col, BKE_brush_color_get(scene, brush)); | rgb_float_to_uchar(col, BKE_brush_color_get(scene, brush)); | ||||
| col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */ | col[3] = 255; /* alpha isn't used, could even be removed to speedup paint a little */ | ||||
| return *(unsigned int *)col; | return *(unsigned int *)col; | ||||
| } | } | ||||
| static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag) | static void do_shared_vertexcol(Mesh *me, bool *mlooptag) | ||||
| { | |||||
| /* if no mcol: do not do */ | |||||
| /* if tface: only the involved faces, otherwise all */ | |||||
| const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; | |||||
| MFace *mface; | |||||
| int a; | |||||
| short *scolmain, *scol; | |||||
| char *mcol; | |||||
| const bool *mftag; | |||||
| if (me->mcol == NULL || me->totvert == 0 || me->totface == 0) return; | |||||
| scolmain = MEM_callocN(4 * sizeof(short) * me->totvert, "colmain"); | |||||
| mface = me->mface; | |||||
| mcol = (char *)me->mcol; | |||||
| for (a = me->totface; a > 0; a--, mface++, mcol += 16) { | |||||
| if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) { | |||||
| 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]; | |||||
| } | |||||
| } | |||||
| } | |||||
| a = me->totvert; | |||||
| scol = scolmain; | |||||
| while (a--) { | |||||
| if (scol[0] > 1) { | |||||
| scol[1] = divide_round_i(scol[1], scol[0]); | |||||
| scol[2] = divide_round_i(scol[2], scol[0]); | |||||
| scol[3] = divide_round_i(scol[3], scol[0]); | |||||
| } | |||||
| scol += 4; | |||||
| } | |||||
| mface = me->mface; | |||||
| mcol = (char *)me->mcol; | |||||
| mftag = mfacetag; | |||||
| for (a = me->totface; a > 0; a--, mface++, mcol += 16, mftag += 4) { | |||||
| if ((use_face_sel == false) || (mface->flag & ME_FACE_SEL)) { | |||||
| if (mftag[0]) { | |||||
| scol = scolmain + 4 * mface->v1; | |||||
| mcol[1] = scol[1]; mcol[2] = scol[2]; mcol[3] = scol[3]; | |||||
| } | |||||
| if (mftag[1]) { | |||||
| scol = scolmain + 4 * mface->v2; | |||||
| mcol[5] = scol[1]; mcol[6] = scol[2]; mcol[7] = scol[3]; | |||||
| } | |||||
| if (mftag[2]) { | |||||
| scol = scolmain + 4 * mface->v3; | |||||
| mcol[9] = scol[1]; mcol[10] = scol[2]; mcol[11] = scol[3]; | |||||
| } | |||||
| if (mface->v4 && mftag[3]) { | |||||
| scol = scolmain + 4 * mface->v4; | |||||
| mcol[13] = scol[1]; mcol[14] = scol[2]; mcol[15] = scol[3]; | |||||
| } | |||||
| } | |||||
| } | |||||
| MEM_freeN(scolmain); | |||||
| } | |||||
| static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface) | |||||
| { | { | ||||
| const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; | const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; | ||||
| MPoly *mp; | MPoly *mp; | ||||
| int (*scol)[4]; | int (*scol)[4]; | ||||
| int i, j; | int i, j; | ||||
| bool has_shared = false; | bool has_shared = false; | ||||
| /* if no mloopcol: do not do */ | /* if no mloopcol: do not do */ | ||||
| Show All 37 Lines | for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) { | ||||
| lcol->b = scol[ml->v][2]; | lcol->b = scol[ml->v][2]; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| MEM_freeN(scol); | MEM_freeN(scol); | ||||
| if (has_shared && do_tessface) { | |||||
| do_shared_vertex_tesscol(me, mfacetag); | |||||
| } | |||||
| } | } | ||||
| static bool make_vertexcol(Object *ob) /* single ob */ | static bool make_vertexcol(Object *ob) /* single ob */ | ||||
| { | { | ||||
| Mesh *me; | Mesh *me; | ||||
| if ((ob->id.lib) || | if ((ob->id.lib) || | ||||
| ((me = BKE_mesh_from_object(ob)) == NULL) || | ((me = BKE_mesh_from_object(ob)) == NULL) || | ||||
| (me->totpoly == 0) || | (me->totpoly == 0) || | ||||
| (me->edit_btmesh)) | (me->edit_btmesh)) | ||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* copies from shadedisplist to mcol */ | /* copies from shadedisplist to mcol */ | ||||
| if (!me->mloopcol && me->totloop) { | if (!me->mloopcol && me->totloop) { | ||||
| if (!me->mcol) { | |||||
| CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface); | |||||
| } | |||||
| if (!me->mloopcol) { | if (!me->mloopcol) { | ||||
| CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); | CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); | ||||
| } | } | ||||
| BKE_mesh_update_customdata_pointers(me, true); | BKE_mesh_update_customdata_pointers(me, true); | ||||
| } | } | ||||
| update_tessface_data(ob, me); | |||||
| DAG_id_tag_update(&me->id, 0); | DAG_id_tag_update(&me->id, 0); | ||||
| return (me->mloopcol != NULL); | return (me->mloopcol != NULL); | ||||
| } | } | ||||
| /* mirror_vgroup is set to -1 when invalid */ | /* mirror_vgroup is set to -1 when invalid */ | ||||
| static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active) | static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | for (i = 0; i < me->totpoly; i++, mp++) { | ||||
| for (j = 0; j < mp->totloop; j++, ml_index++, ml++) { | for (j = 0; j < mp->totloop; j++, ml_index++, ml++) { | ||||
| mlooptag[ml_index] = true; | mlooptag[ml_index] = true; | ||||
| } | } | ||||
| } | } | ||||
| /* remove stale me->mcol, will be added later */ | /* remove stale me->mcol, will be added later */ | ||||
| BKE_mesh_tessface_clear(me); | BKE_mesh_tessface_clear(me); | ||||
| do_shared_vertexcol(me, mlooptag, NULL, false); | do_shared_vertexcol(me, mlooptag); | ||||
| MEM_freeN(mlooptag); | MEM_freeN(mlooptag); | ||||
| DAG_id_tag_update(&me->id, 0); | DAG_id_tag_update(&me->id, 0); | ||||
| return true; | return true; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 2,143 Lines • ▼ Show 20 Lines | typedef struct VPaintData { | ||||
| DMCoNo *vertexcosnos; | DMCoNo *vertexcosnos; | ||||
| float vpimat[3][3]; | float vpimat[3][3]; | ||||
| /* modify 'me->mcol' directly, since the derived mesh is drawing from this | /* modify 'me->mcol' directly, since the derived mesh is drawing from this | ||||
| * array, otherwise we need to refresh the modifier stack */ | * array, otherwise we need to refresh the modifier stack */ | ||||
| bool use_fast_update; | bool use_fast_update; | ||||
| /* mpoly -> mface mapping */ | |||||
| MeshElemMap *polyfacemap; | |||||
| void *polyfacemap_mem; | |||||
| /* loops tagged as having been painted, to apply shared vertex color | /* loops tagged as having been painted, to apply shared vertex color | ||||
| * blending only to modified loops */ | * blending only to modified loops */ | ||||
| bool *mlooptag; | bool *mlooptag; | ||||
| bool *mfacetag; | |||||
| bool is_texbrush; | bool is_texbrush; | ||||
| } VPaintData; | } VPaintData; | ||||
| static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) | |||||
| { | |||||
| const int *tessface_origindex; | |||||
| vd->polyfacemap = NULL; | |||||
| vd->polyfacemap_mem = NULL; | |||||
| tessface_origindex = CustomData_get_layer(&me->fdata, CD_ORIGINDEX); | |||||
| if (!tessface_origindex) | |||||
| return; | |||||
| BKE_mesh_origindex_map_create(&vd->polyfacemap, (int **)&vd->polyfacemap_mem, | |||||
| me->totpoly, | |||||
| tessface_origindex, me->totface); | |||||
| } | |||||
| static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2])) | static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const float UNUSED(mouse[2])) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ToolSettings *ts = scene->toolsettings; | ToolSettings *ts = scene->toolsettings; | ||||
| struct PaintStroke *stroke = op->customdata; | struct PaintStroke *stroke = op->customdata; | ||||
| VPaint *vp = ts->vpaint; | VPaint *vp = ts->vpaint; | ||||
| Brush *brush = BKE_paint_brush(&vp->paint); | Brush *brush = BKE_paint_brush(&vp->paint); | ||||
| struct VPaintData *vpd; | struct VPaintData *vpd; | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| Mesh *me; | Mesh *me; | ||||
| float mat[4][4], imat[4][4]; | float mat[4][4], imat[4][4]; | ||||
| /* context checks could be a poll() */ | /* context checks could be a poll() */ | ||||
| me = BKE_mesh_from_object(ob); | me = BKE_mesh_from_object(ob); | ||||
| if (me == NULL || me->totpoly == 0) | if (me == NULL || me->totpoly == 0) | ||||
| return false; | return false; | ||||
| if (me->mloopcol == NULL) | if (me->mloopcol == NULL) | ||||
| make_vertexcol(ob); | make_vertexcol(ob); | ||||
| if (me->mloopcol == NULL) | if (me->mloopcol == NULL) | ||||
| return false; | return false; | ||||
| /* Update tessface data if needed | |||||
| * Added here too because e.g. switching to/from edit mode would remove tessface data, | |||||
| * yet "fast_update" could still be used! */ | |||||
| update_tessface_data(ob, me); | |||||
| /* make mode data storage */ | /* make mode data storage */ | ||||
| vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData"); | vpd = MEM_callocN(sizeof(struct VPaintData), "VPaintData"); | ||||
| paint_stroke_set_mode_data(stroke, vpd); | paint_stroke_set_mode_data(stroke, vpd); | ||||
| view3d_set_viewcontext(C, &vpd->vc); | view3d_set_viewcontext(C, &vpd->vc); | ||||
| vpd->vp_handle = ED_vpaint_proj_handle_create(vpd->vc.scene, ob, &vpd->vertexcosnos); | vpd->vp_handle = ED_vpaint_proj_handle_create(vpd->vc.scene, ob, &vpd->vertexcosnos); | ||||
| vpd->indexar = get_indexarray(me); | vpd->indexar = get_indexarray(me); | ||||
| vpd->paintcol = vpaint_get_current_col(scene, vp); | vpd->paintcol = vpaint_get_current_col(scene, vp); | ||||
| vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) && | vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) && | ||||
| brush->mtex.tex; | brush->mtex.tex; | ||||
| /* are we painting onto a modified mesh?, | /* are we painting onto a modified mesh?, | ||||
| * if not we can skip face map trickyness */ | * if not we can skip face map trickyness */ | ||||
| if (vertex_paint_use_fast_update_check(ob)) { | if (vertex_paint_use_fast_update_check(ob)) { | ||||
| vpaint_build_poly_facemap(vpd, me); | |||||
| vpd->use_fast_update = true; | vpd->use_fast_update = true; | ||||
| /* printf("Fast update!\n");*/ | /* printf("Fast update!\n");*/ | ||||
| } | } | ||||
| else { | else { | ||||
| vpd->use_fast_update = false; | vpd->use_fast_update = false; | ||||
| /* printf("No fast update!\n");*/ | /* printf("No fast update!\n");*/ | ||||
| } | } | ||||
| /* to keep tracked of modified loops for shared vertex color blending */ | /* to keep tracked of modified loops for shared vertex color blending */ | ||||
| if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { | if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { | ||||
| vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag"); | vpd->mlooptag = MEM_mallocN(sizeof(bool) * me->totloop, "VPaintData mlooptag"); | ||||
| if (vpd->use_fast_update) | |||||
| vpd->mfacetag = MEM_mallocN(sizeof(bool) * me->totface * 4, "VPaintData mfacetag"); | |||||
| } | } | ||||
| /* for filtering */ | /* for filtering */ | ||||
| copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop); | copy_vpaint_prev(vp, (unsigned int *)me->mloopcol, me->totloop); | ||||
| /* some old cruft to sort out later */ | /* some old cruft to sort out later */ | ||||
| mul_m4_m4m4(mat, vpd->vc.rv3d->viewmat, ob->obmat); | mul_m4_m4m4(mat, vpd->vc.rv3d->viewmat, ob->obmat); | ||||
| invert_m4_m4(imat, mat); | invert_m4_m4(imat, mat); | ||||
| copy_m3_m4(vpd->vpimat, imat); | copy_m3_m4(vpd->vpimat, imat); | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, | static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, | ||||
| const unsigned int index, const float mval[2], | const unsigned int index, const float mval[2], | ||||
| const float brush_size_pressure, const float brush_alpha_pressure) | const float brush_size_pressure, const float brush_alpha_pressure) | ||||
| { | { | ||||
| ViewContext *vc = &vpd->vc; | ViewContext *vc = &vpd->vc; | ||||
| Brush *brush = BKE_paint_brush(&vp->paint); | Brush *brush = BKE_paint_brush(&vp->paint); | ||||
| MPoly *mpoly = &me->mpoly[index]; | MPoly *mpoly = &me->mpoly[index]; | ||||
| MFace *mf; | |||||
| MCol *mc; | |||||
| MLoop *ml; | MLoop *ml; | ||||
| MLoopCol *mlc; | |||||
| unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart; | unsigned int *lcol = ((unsigned int *)me->mloopcol) + mpoly->loopstart; | ||||
| unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart; | unsigned int *lcolorig = ((unsigned int *)vp->vpaint_prev) + mpoly->loopstart; | ||||
| bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL; | bool *mlooptag = (vpd->mlooptag) ? vpd->mlooptag + mpoly->loopstart : NULL; | ||||
| bool *mftag; | |||||
| float alpha; | float alpha; | ||||
| int i, j; | int i, j; | ||||
| int totloop = mpoly->totloop; | int totloop = mpoly->totloop; | ||||
| int brush_alpha_pressure_i = (int)(brush_alpha_pressure * 255.0f); | int brush_alpha_pressure_i = (int)(brush_alpha_pressure * 255.0f); | ||||
| if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { | if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { | ||||
| unsigned int blend[4] = {0}; | unsigned int blend[4] = {0}; | ||||
| Show All 40 Lines | for (i = 0; i < totloop; i++, ml++) { | ||||
| if (alpha > 0.0f) { | if (alpha > 0.0f) { | ||||
| const int alpha_i = (int)(alpha * 255.0f); | const int alpha_i = (int)(alpha * 255.0f); | ||||
| lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], paintcol, alpha_i, brush_alpha_pressure_i); | lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], paintcol, alpha_i, brush_alpha_pressure_i); | ||||
| if (mlooptag) mlooptag[i] = 1; | if (mlooptag) mlooptag[i] = 1; | ||||
| } | } | ||||
| } | } | ||||
| if (vpd->use_fast_update) { | |||||
| const MeshElemMap *map = &vpd->polyfacemap[index]; | |||||
| /* update vertex colors for tessellations incrementally, | |||||
| * rather then regenerating the tessellation altogether */ | |||||
| for (i = 0; i < map->count; i++) { | |||||
| const int index_tessface = map->indices[i]; | |||||
| mf = &me->mface[index_tessface]; | |||||
| mc = &me->mcol[index_tessface * 4]; | |||||
| mftag = &vpd->mfacetag[index_tessface * 4]; | |||||
| ml = me->mloop + mpoly->loopstart; | |||||
| mlc = me->mloopcol + mpoly->loopstart; | |||||
| for (j = 0; j < totloop; j++, ml++, mlc++) { | |||||
| /* search for the loop vertex within the tessface */ | |||||
| const int fidx = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml->v); | |||||
| if (fidx != -1) { | |||||
| MESH_MLOOPCOL_TO_MCOL(mlc, mc + fidx); | |||||
| if (mlooptag) { | |||||
| mftag[fidx] = mlooptag[j]; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) | static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ToolSettings *ts = CTX_data_tool_settings(C); | ToolSettings *ts = CTX_data_tool_settings(C); | ||||
| struct VPaintData *vpd = paint_stroke_mode_data(stroke); | struct VPaintData *vpd = paint_stroke_mode_data(stroke); | ||||
| VPaint *vp = ts->vpaint; | VPaint *vp = ts->vpaint; | ||||
| Show All 35 Lines | static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) | ||||
| swap_m4m4(vc->rv3d->persmat, mat); | swap_m4m4(vc->rv3d->persmat, mat); | ||||
| /* incase we have modifiers */ | /* incase we have modifiers */ | ||||
| ED_vpaint_proj_handle_update(vpd->vp_handle, vc->ar, mval); | ED_vpaint_proj_handle_update(vpd->vp_handle, vc->ar, mval); | ||||
| /* clear modified tag for blur tool */ | /* clear modified tag for blur tool */ | ||||
| if (vpd->mlooptag) | if (vpd->mlooptag) | ||||
| memset(vpd->mlooptag, 0, sizeof(bool) * me->totloop); | memset(vpd->mlooptag, 0, sizeof(bool) * me->totloop); | ||||
| if (vpd->mfacetag) | |||||
| memset(vpd->mfacetag, 0, sizeof(bool) * me->totface * 4); | |||||
| for (index = 0; index < totindex; index++) { | for (index = 0; index < totindex; index++) { | ||||
| if (indexar[index] && indexar[index] <= me->totpoly) { | if (indexar[index] && indexar[index] <= me->totpoly) { | ||||
| vpaint_paint_poly(vp, vpd, me, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure); | vpaint_paint_poly(vp, vpd, me, indexar[index] - 1, mval, brush_size_pressure, brush_alpha_pressure); | ||||
| } | } | ||||
| } | } | ||||
| swap_m4m4(vc->rv3d->persmat, mat); | swap_m4m4(vc->rv3d->persmat, mat); | ||||
| /* was disabled because it is slow, but necessary for blur */ | /* was disabled because it is slow, but necessary for blur */ | ||||
| if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { | if (brush->vertexpaint_tool == PAINT_BLEND_BLUR) { | ||||
| int do_tessface = vpd->use_fast_update; | do_shared_vertexcol(me, vpd->mlooptag); | ||||
| do_shared_vertexcol(me, vpd->mlooptag, vpd->mfacetag, do_tessface); | |||||
| } | } | ||||
| ED_region_tag_redraw(vc->ar); | ED_region_tag_redraw(vc->ar); | ||||
| if (vpd->use_fast_update == false) { | if (vpd->use_fast_update == false) { | ||||
| /* recalculate modifier stack to get new colors, slow, | /* recalculate modifier stack to get new colors, slow, | ||||
| * avoid this if we can! */ | * avoid this if we can! */ | ||||
| DAG_id_tag_update(ob->data, 0); | DAG_id_tag_update(ob->data, 0); | ||||
| Show All 12 Lines | static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) | ||||
| Object *ob = vc->obact; | Object *ob = vc->obact; | ||||
| ED_vpaint_proj_handle_free(vpd->vp_handle); | ED_vpaint_proj_handle_free(vpd->vp_handle); | ||||
| MEM_freeN(vpd->indexar); | MEM_freeN(vpd->indexar); | ||||
| /* frees prev buffer */ | /* frees prev buffer */ | ||||
| copy_vpaint_prev(ts->vpaint, NULL, 0); | copy_vpaint_prev(ts->vpaint, NULL, 0); | ||||
| if (vpd->polyfacemap) { | |||||
| MEM_freeN(vpd->polyfacemap); | |||||
| } | |||||
| if (vpd->polyfacemap_mem) { | |||||
| MEM_freeN(vpd->polyfacemap_mem); | |||||
| } | |||||
| if (vpd->mlooptag) | if (vpd->mlooptag) | ||||
| MEM_freeN(vpd->mlooptag); | MEM_freeN(vpd->mlooptag); | ||||
| if (vpd->mfacetag) | |||||
| MEM_freeN(vpd->mfacetag); | |||||
| WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | ||||
| MEM_freeN(vpd); | MEM_freeN(vpd); | ||||
| } | } | ||||
| static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| int retval; | int retval; | ||||
| ▲ Show 20 Lines • Show All 420 Lines • Show Last 20 Lines | |||||