diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-06-26 22:40:55 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-06-26 22:40:55 +0400 |
commit | ca51930a90056aa3a65dcfc086ddd9ad19dcdf0f (patch) | |
tree | 8aab10f95727869b1e105a2ed9cb0a12f3cd84da /source | |
parent | 9c85cdceb2544740682490a07a3d3f77612f9691 (diff) |
fix [#33068] Can't paint weights of some vertices in some situations.
old limitation where you could only paint onto one side of a mirrored mesh (weight paint, vertex paint).
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 4 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_intern.h | 15 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex.c | 41 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex_proj.c | 244 |
6 files changed, 286 insertions, 22 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index bd2a9423649..fdb43f5467e 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -615,10 +615,13 @@ void DM_interp_poly_data(struct DerivedMesh *source, struct DerivedMesh *dest, /* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */ void vDM_ColorBand_store(const struct ColorBand *coba, const char alert_color[4]); +/* UNUSED */ +#if 0 /** Simple function to get me->totvert amount of vertices/normals, * correctly deformed and subsurfered. Needed especially when vertexgroups are involved. * In use now by vertex/weight paint and particles */ DMCoNo *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob); +#endif /* */ DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob, diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 96ccc5be8e0..aeb664b3c2f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2432,6 +2432,8 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em) return getEditDerivedBMesh(em, obedit, NULL); } +/* UNUSED */ +#if 0 /* ********* For those who don't grasp derived stuff! (ton) :) *************** */ @@ -2488,6 +2490,8 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) return vertexcosnos; } +#endif + /* ******************* GLSL ******************** */ typedef struct { diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 9b46a07b60e..79ce4f879b7 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC paint_undo.c paint_utils.c paint_vertex.c + paint_vertex_proj.c sculpt.c sculpt_undo.c sculpt_uv.c diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index df0fb8ec4f8..6c13f6efb74 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -54,6 +54,7 @@ struct wmOperator; struct wmOperatorType; struct ImagePaintState; struct wmWindowManager; +struct DMCoNo; enum PaintMode; /* paint_stroke.c */ @@ -115,6 +116,20 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot); unsigned int vpaint_get_current_col(struct VPaint *vp); + +/* paint_vertex_proj.c */ +struct VertProjHandle; +struct VertProjHandle *ED_vpaint_proj_handle_create( + struct Scene *scene, struct Object *ob, + struct DMCoNo **r_vcosnos); +void ED_vpaint_proj_handle_update( + struct VertProjHandle *vp_handle, + /* runtime vars */ + struct ARegion *ar, const float mval_fl[2]); +void ED_vpaint_proj_handle_free( + struct VertProjHandle *vp_handle); + + /* paint_image.c */ typedef struct ImagePaintPartialRedraw { int x1, y1, x2, y2; /* XXX, could use 'rcti' */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 181b32d58fc..158a6a92536 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -29,24 +29,11 @@ * \ingroup edsculpt */ - -#include <math.h> -#include <string.h> - -#ifdef WIN32 -#include <io.h> -#else -#include <unistd.h> -#endif - #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_math.h" -#include "BLI_math_color.h" #include "BLI_memarena.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -57,14 +44,12 @@ #include "DNA_scene_types.h" #include "DNA_brush_types.h" #include "DNA_object_types.h" -#include "DNA_meshdata_types.h" #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" #include "BKE_DerivedMesh.h" -#include "BKE_armature.h" #include "BKE_action.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -87,7 +72,7 @@ #include "ED_screen.h" #include "ED_view3d.h" -#include "paint_intern.h" +#include "paint_intern.h" /* own include */ /* check if we can do partial updates and have them draw realtime * (without rebuilding the 'derivedFinal') */ @@ -2135,7 +2120,10 @@ struct WPaintData { int *indexar; int vgroup_active; int vgroup_mirror; + + void *vp_handle; DMCoNo *vertexcosnos; + float wpimat[3][3]; /* variables for auto normalize */ @@ -2244,7 +2232,8 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU } /* painting on subsurfs should give correct points too, this returns me->totvert amount */ - wpd->vertexcosnos = mesh_get_mapped_verts_nors(scene, ob); + wpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &wpd->vertexcosnos); + wpd->indexar = get_indexarray(me); copy_wpaint_prev(wp, me->dvert, me->totvert); @@ -2378,6 +2367,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P indexar = NULL; } + /* incase we have modifiers */ + ED_vpaint_proj_handle_update(wpd->vp_handle, vc->ar, mval); + /* make sure each vertex gets treated only once */ /* and calculate filter weight */ totw = 0.0f; @@ -2516,8 +2508,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) struct WPaintData *wpd = paint_stroke_mode_data(stroke); if (wpd) { - if (wpd->vertexcosnos) - MEM_freeN(wpd->vertexcosnos); + ED_vpaint_proj_handle_free(wpd->vp_handle); MEM_freeN(wpd->indexar); if (wpd->vgroup_validmap) @@ -2750,7 +2741,10 @@ typedef struct VPaintData { ViewContext vc; unsigned int paintcol; int *indexar; + + struct VertProjHandle *vp_handle; DMCoNo *vertexcosnos; + float vpimat[3][3]; /* modify 'me->mcol' directly, since the derived mesh is drawing from this @@ -2829,7 +2823,8 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl paint_stroke_set_mode_data(stroke, vpd); view3d_set_viewcontext(C, &vpd->vc); - vpd->vertexcosnos = mesh_get_mapped_verts_nors(vpd->vc.scene, ob); + vpd->vp_handle = ED_vpaint_proj_handle_create(vpd->vc.scene, ob, &vpd->vertexcosnos); + vpd->indexar = get_indexarray(me); vpd->paintcol = vpaint_get_current_col(vp); @@ -3027,6 +3022,9 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P swap_m4m4(vc->rv3d->persmat, mat); + /* incase we have modifiers */ + ED_vpaint_proj_handle_update(vpd->vp_handle, vc->ar, mval); + /* clear modified tag for blur tool */ if (vpd->mlooptag) memset(vpd->mlooptag, 0, sizeof(bool) * me->totloop); @@ -3072,8 +3070,7 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) ViewContext *vc = &vpd->vc; Object *ob = vc->obact; - if (vpd->vertexcosnos) - MEM_freeN(vpd->vertexcosnos); + ED_vpaint_proj_handle_free(vpd->vp_handle); MEM_freeN(vpd->indexar); /* frees prev buffer */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex_proj.c b/source/blender/editors/sculpt_paint/paint_vertex_proj.c new file mode 100644 index 00000000000..51734447d1d --- /dev/null +++ b/source/blender/editors/sculpt_paint/paint_vertex_proj.c @@ -0,0 +1,244 @@ +/* + * ***** BEGIN GPL 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. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/sculpt_paint/paint_vertex_proj.c + * \ingroup edsculpt + * + * Utility functions for getting vertex locations while painting + * (since they may be instanced multiple times in a DerivedMesh) + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_context.h" + +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "paint_intern.h" /* own include */ + + +/* Opaque Structs for internal use */ + +/* stored while painting */ +struct VertProjHandle { + DMCoNo *vcosnos; + + bool use_update; + + /* use for update */ + float *dists; + + Object *ob; + Scene *scene; +}; + +/* only for passing to the callbacks */ +struct VertProjUpdate { + struct VertProjHandle *vp_handle; + + /* runtime */ + ARegion *ar; + const float *mval_fl; +}; + + +/* -------------------------------------------------------------------- */ +/* Internal Init */ + +static void vpaint_proj_dm_map_cosnos_init__map_cb(void *userData, int index, const float co[3], + const float no_f[3], const short no_s[3]) +{ + struct VertProjHandle *vp_handle = userData; + DMCoNo *co_no = &vp_handle->vcosnos[index]; + + /* check if we've been here before (normal should not be 0) */ + if (!is_zero_v3(co_no->no)) { + /* remember that multiple dm verts share the same source vert */ + vp_handle->use_update = true; + return; + } + + copy_v3_v3(co_no->co, co); + if (no_f) { + copy_v3_v3(co_no->no, no_f); + } + else { + normal_short_to_float_v3(co_no->no, no_s); + } +} + +static void vpaint_proj_dm_map_cosnos_init(Scene *scene, Object *ob, + struct VertProjHandle *vp_handle) +{ + Mesh *me = ob->data; + DerivedMesh *dm; + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); + + if (dm->foreachMappedVert) { + memset(vp_handle->vcosnos, 0, sizeof(DMCoNo) * me->totvert); + dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_init__map_cb, vp_handle); + } + else { + DMCoNo *v_co_no = vp_handle->vcosnos; + int a; + for (a = 0; a < me->totvert; a++, v_co_no++) { + dm->getVertCo(dm, a, v_co_no->co); + dm->getVertNo(dm, a, v_co_no->no); + } + } + + dm->release(dm); +} + + +/* -------------------------------------------------------------------- */ +/* Internal Update */ + +/* Same as init but take mouse location into account */ + +static void vpaint_proj_dm_map_cosnos_update__map_cb(void *userData, int index, const float co[3], + const float no_f[3], const short no_s[3]) +{ + struct VertProjUpdate *vp_update = userData; + struct VertProjHandle *vp_handle = vp_update->vp_handle; + + DMCoNo *co_no = &vp_handle->vcosnos[index]; + + /* find closest vertex */ + { + /* first find distance to this vertex */ + float co_ss[2]; /* screenspace */ + + if (ED_view3d_project_float_object(vp_update->ar, + co, co_ss, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) + { + const float dist = len_squared_v2v2(vp_update->mval_fl, co_ss); + if (dist > vp_handle->dists[index]) { + /* bail out! */ + return; + } + + vp_handle->dists[index] = dist; + } + } + /* continue with regular functionality */ + + copy_v3_v3(co_no->co, co); + if (no_f) { + copy_v3_v3(co_no->no, no_f); + } + else { + normal_short_to_float_v3(co_no->no, no_s); + } +} + +static void vpaint_proj_dm_map_cosnos_update(struct VertProjHandle *vp_handle, + ARegion *ar, const float mval_fl[2]) +{ + struct VertProjUpdate vp_update = {vp_handle, ar, mval_fl}; + + Scene *scene = vp_handle->scene; + Object *ob = vp_handle->ob; + Mesh *me = ob->data; + DerivedMesh *dm; + + /* quick sanity check - we shouldn't have to run this if there are no modifiers */ + BLI_assert(ob->modifiers.first != NULL); + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); + + /* highly unlikely this will become unavailable once painting starts (perhaps with animated modifiers) */ + if (LIKELY(dm->foreachMappedVert)) { + fill_vn_fl(vp_handle->dists, me->totvert, FLT_MAX); + + dm->foreachMappedVert(dm, vpaint_proj_dm_map_cosnos_update__map_cb, &vp_update); + } + + dm->release(dm); + + (void)mval_fl; +} + + +/* -------------------------------------------------------------------- */ +/* Public Functions */ + +struct VertProjHandle *ED_vpaint_proj_handle_create(Scene *scene, Object *ob, + DMCoNo **r_vcosnos) +{ + struct VertProjHandle *vp_handle = MEM_mallocN(sizeof(struct VertProjHandle), __func__); + Mesh *me = ob->data; + + /* setup the handle */ + vp_handle->vcosnos = MEM_mallocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); + vp_handle->use_update = false; + + /* sets 'use_update' if needed */ + vpaint_proj_dm_map_cosnos_init(scene, ob, vp_handle); + + if (vp_handle->use_update) { + vp_handle->dists = MEM_mallocN(sizeof(float) * me->totvert, __func__); + + vp_handle->ob = ob; + vp_handle->scene = scene; + } + else { + vp_handle->dists = NULL; + + vp_handle->ob = NULL; + vp_handle->scene = NULL; + } + + *r_vcosnos = vp_handle->vcosnos; + return vp_handle; +} + +void ED_vpaint_proj_handle_update(struct VertProjHandle *vp_handle, + ARegion *ar, const float mval_fl[2]) +{ + if (vp_handle->use_update) { + vpaint_proj_dm_map_cosnos_update(vp_handle, ar, mval_fl); + } +} + +void ED_vpaint_proj_handle_free(struct VertProjHandle *vp_handle) +{ + if (vp_handle->use_update) { + MEM_freeN(vp_handle->dists); + } + + MEM_freeN(vp_handle->vcosnos); + MEM_freeN(vp_handle); +} |