Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-09-27 18:38:17 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-09-27 18:47:37 +0300
commit4f616c93f7cb8c8c8e038bc0c949c931242971c2 (patch)
treef696051e640c757ef2fdacce463d04b7ebb32838 /source/blender/blenkernel/intern
parent2de5e14f53e9a439ae87deb16f816ec71445c1ba (diff)
Vertex/Weight Paint: Use PBVH for painting
2016 GSOC project by @nathanvollmer, see D2150 - Mirrored painting and radial symmetry, like in sculpt mode. - Volume based splash prevention, which avoids painting vertices far away from the 3D brush location. - Normal based splash prevention, which avoids painting vertices with normals opposite the normal at the 3D brush location. - Blur mode now uses a nearest neighbor average. - Average mode, which averages the color/weight of the vertices within the brush - Smudge mode, which pulls the colors/weights along the direction of the brush - RGB^2 color blending, which gives a more accurate blend between two colors - multithreading support. (PBVH leaves are painted in parallel.) - Foreground/background color picker in vertex paint
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c2
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c5
-rw-r--r--source/blender/blenkernel/intern/object.c5
-rw-r--r--source/blender/blenkernel/intern/paint.c35
-rw-r--r--source/blender/blenkernel/intern/pbvh.c14
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h2
-rw-r--r--source/blender/blenkernel/intern/scene.c12
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c20
8 files changed, 72 insertions, 23 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index ace79f4125b..9dae4c5eae7 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2663,7 +2663,7 @@ static void mesh_build_data(
ob->lastDataMask = dataMask;
ob->lastNeedMapping = need_mapping;
- if ((ob->mode & OB_MODE_SCULPT) && ob->sculpt) {
+ if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
/* create PBVH immediately (would be created on the fly too,
* but this avoids waiting on first stroke) */
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 2c61cf28691..e97de07752e 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -662,6 +662,11 @@ static void cdDM_drawMappedFaces(
const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+ if (cddm->pbvh) {
+ if (G.debug_value == 14)
+ BKE_pbvh_draw_BB(cddm->pbvh);
+ }
+
/* fist, setup common buffers */
GPU_vertex_setup(dm);
GPU_triangle_setup(dm);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index d76ef613023..44058c989ff 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2682,7 +2682,7 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
{
SculptSession *ss = ob->sculpt;
- if (ss) {
+ if (ss && ss->building_vp_handle == false) {
if (!ss->cache) {
/* we free pbvh on changes, except during sculpt since it can't deal with
* changing PVBH node organization, we hope topology does not change in
@@ -2693,6 +2693,9 @@ void BKE_object_sculpt_modifiers_changed(Object *ob)
}
BKE_sculptsession_free_deformMats(ob->sculpt);
+
+ /* In vertex/weight paint, force maps to be rebuilt. */
+ BKE_sculptsession_free_vwpaint_data(ob->sculpt);
}
else {
PBVHNode **nodes;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9fc2136df86..25ea6ad079f 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -673,6 +673,29 @@ void BKE_sculptsession_free_deformMats(SculptSession *ss)
MEM_SAFE_FREE(ss->deform_imats);
}
+void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss)
+{
+ struct SculptVertexPaintGeomMap *gmap = NULL;
+ if (ss->mode_type == OB_MODE_VERTEX_PAINT) {
+ gmap = &ss->mode.vpaint.gmap;
+
+ MEM_SAFE_FREE(ss->mode.vpaint.previous_color);
+ }
+ else if (ss->mode_type == OB_MODE_WEIGHT_PAINT) {
+ gmap = &ss->mode.wpaint.gmap;
+
+ MEM_SAFE_FREE(ss->mode.wpaint.alpha_weight);
+ MEM_SAFE_FREE(ss->mode.wpaint.previous_weight);
+ }
+ else {
+ return;
+ }
+ MEM_SAFE_FREE(gmap->vert_to_loop);
+ MEM_SAFE_FREE(gmap->vert_map_mem);
+ MEM_SAFE_FREE(gmap->vert_to_poly);
+ MEM_SAFE_FREE(gmap->poly_map_mem);
+}
+
/* Write out the sculpt dynamic-topology BMesh to the Mesh */
static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
{
@@ -714,10 +737,7 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object)
*/
BKE_object_free_derived_caches(object);
- if (object->sculpt->pbvh) {
- BKE_pbvh_free(object->sculpt->pbvh);
- object->sculpt->pbvh = NULL;
- }
+ MEM_SAFE_FREE(object->sculpt->pbvh);
sculptsession_bm_to_me_update_data_only(object, false);
@@ -764,6 +784,8 @@ void BKE_sculptsession_free(Object *ob)
if (ss->deform_imats)
MEM_freeN(ss->deform_imats);
+ BKE_sculptsession_free_vwpaint_data(ob->sculpt);
+
MEM_freeN(ss);
ob->sculpt = NULL;
@@ -848,6 +870,8 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->modifiers_active = sculpt_modifiers_active(scene, sd, ob);
ss->show_diffuse_color = (sd->flags & SCULPT_SHOW_DIFFUSE) != 0;
+ ss->building_vp_handle = false;
+
if (need_mask) {
if (mmd == NULL) {
if (!CustomData_has_layer(&me->vdata, CD_PAINT_MASK)) {
@@ -876,7 +900,8 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- if (mmd) {
+ /* VWPaint require mesh info for loop lookup, so require sculpt mode here */
+ if (mmd && ob->mode & OB_MODE_SCULPT) {
ss->multires = mmd;
ss->totvert = dm->getNumVerts(dm);
ss->totpoly = dm->getNumPolys(dm);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 53dfffe2b97..4b154d3301c 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -34,6 +34,7 @@
#include "BKE_pbvh.h"
#include "BKE_ccg.h"
+#include "BKE_subsurf.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
@@ -606,6 +607,10 @@ void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids,
MEM_freeN(prim_bbc);
}
+void BKE_pbvh_set_ccgdm(PBVH *bvh, CCGDerivedMesh *ccgdm) {
+ bvh->ccgdm = ccgdm;
+}
+
PBVH *BKE_pbvh_new(void)
{
PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
@@ -1156,7 +1161,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
}
}
-static void pbvh_draw_BB(PBVH *bvh)
+void BKE_pbvh_draw_BB(PBVH *bvh)
{
GPU_pbvh_BB_draw_init();
@@ -1329,6 +1334,11 @@ void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
*key = bvh->gridkey;
}
+CCGDerivedMesh *BKE_pbvh_get_ccgdm(const PBVH *bvh) {
+ return bvh->ccgdm;
+}
+
+
BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
{
BLI_assert(bvh->type == PBVH_BMESH);
@@ -1860,7 +1870,7 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3],
}
if (G.debug_value == 14)
- pbvh_draw_BB(bvh);
+ BKE_pbvh_draw_BB(bvh);
}
void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 19d3b31bd31..01057318568 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -149,6 +149,8 @@ struct PBVH {
* objects in sculpt mode with different sizes at the same time, so now storing that common gpu buffer
* in an opaque pointer per pbvh. See T47637. */
struct GridCommonGPUBuffer *grid_common_gpu_buffer;
+ /* The ccgdm is required for CD_ORIGINDEX lookup in vertex paint + multires */
+ struct CCGDerivedMesh *ccgdm;
/* Only used during BVH build and update,
* don't need to remain valid after */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 5b809386267..c0dcac33656 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -217,16 +217,10 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings);
if (ts->vpaint) {
ts->vpaint = MEM_dupallocN(ts->vpaint);
- ts->vpaint->paintcursor = NULL;
- ts->vpaint->vpaint_prev = NULL;
- ts->vpaint->wpaint_prev = NULL;
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata);
}
if (ts->wpaint) {
ts->wpaint = MEM_dupallocN(ts->wpaint);
- ts->wpaint->paintcursor = NULL;
- ts->wpaint->vpaint_prev = NULL;
- ts->wpaint->wpaint_prev = NULL;
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata);
}
if (ts->sculpt) {
@@ -335,16 +329,10 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
if (ts) {
if (ts->vpaint) {
ts->vpaint = MEM_dupallocN(ts->vpaint);
- ts->vpaint->paintcursor = NULL;
- ts->vpaint->vpaint_prev = NULL;
- ts->vpaint->wpaint_prev = NULL;
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0);
}
if (ts->wpaint) {
ts->wpaint = MEM_dupallocN(ts->wpaint);
- ts->wpaint->paintcursor = NULL;
- ts->wpaint->vpaint_prev = NULL;
- ts->wpaint->wpaint_prev = NULL;
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0);
}
if (ts->sculpt) {
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f4ff4dfa019..7c5ee42b7bc 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3683,6 +3683,11 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm,
int gridFaces = gridSize - 1, totface;
int prev_mat_nr = -1;
+ if (ccgdm->pbvh) {
+ if (G.debug_value == 14)
+ BKE_pbvh_draw_BB(ccgdm->pbvh);
+ }
+
#ifdef WITH_OPENSUBDIV
if (ccgdm->useGpuBackend) {
int new_matnr;
@@ -4416,7 +4421,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
if (!ob->sculpt)
return NULL;
- grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
+ /* In vwpaint, we always use a grid_pbvh for multires/subsurf */
+ grid_pbvh = (!(ob->mode & OB_MODE_SCULPT) || ccgDM_use_grid_pbvh(ccgdm));
if (ob->sculpt->pbvh) {
if (grid_pbvh) {
@@ -4432,12 +4438,18 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
ccgdm->pbvh = ob->sculpt->pbvh;
}
- if (ccgdm->pbvh)
+ if (ccgdm->pbvh) {
+ /* For vertex paint, keep track of ccgdm */
+ if (!(ob->mode & OB_MODE_SCULPT)) {
+ BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
+ }
return ccgdm->pbvh;
+ }
/* no pbvh exists yet, we need to create one. only in case of multires
* we build a pbvh over the modified mesh, in other cases the base mesh
* is being sculpted, so we build a pbvh from that. */
+ /* Note: vwpaint always builds a pbvh over the modified mesh. */
if (grid_pbvh) {
ccgdm_create_grids(dm);
@@ -4468,6 +4480,10 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
if (ccgdm->pbvh)
pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
+ /* For vertex paint, keep track of ccgdm */
+ if (!(ob->mode & OB_MODE_SCULPT) && ccgdm->pbvh) {
+ BKE_pbvh_set_ccgdm(ccgdm->pbvh, ccgdm);
+ }
return ccgdm->pbvh;
}