1
1

Compare commits

...

8 Commits

Author SHA1 Message Date
8d72d1cca7 quiet warning 2015-03-24 01:41:19 +11:00
89572e277d Merge branch 'master' into vertex_paint_pbvh 2015-03-24 01:38:01 +11:00
5e224fb934 Fix silly error in last merge 2015-02-26 16:24:07 +01:00
366663a7e0 Merge branch 'master' into vertex_paint_pbvh
Conflicts:
	source/blender/editors/sculpt_paint/sculpt.c
2015-02-26 16:20:10 +01:00
10aee127d4 WIP incorrect inconvenient code that is supposed to draw PBVH colors. 2015-01-02 13:38:04 +01:00
0e41965f76 Cleanup and compile fix after merge 2014-12-29 12:57:28 +01:00
b253ed3b0f Merge branch 'master' into vertex_paint_pbvh
Conflicts:
	source/blender/editors/sculpt_paint/sculpt.c
2014-12-29 12:45:09 +01:00
89333638a8 Vertex painting PBVH refactor:
Refactor PBVH off SculptSession and in a separate PaintSession struct
Entering Vertex painting will generate a PBVH and vertex painting now
draws using PBVH.
Add stub vertex painting operator that will use PBVH.
2014-12-24 14:42:10 +01:00
30 changed files with 928 additions and 397 deletions

View File

@@ -149,6 +149,7 @@ void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brus
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
/* Session data (mode-specific) */
typedef struct SculptSession {
@@ -173,8 +174,6 @@ typedef struct SculptSession {
/* Undo/redo log for dynamic topology sculpting */
struct BMLog *bm_log;
/* PBVH acceleration structure */
struct PBVH *pbvh;
bool show_diffuse_color;
/* Painting on deformed mesh */
@@ -182,14 +181,7 @@ typedef struct SculptSession {
float (*orig_cos)[3]; /* coords of undeformed mesh */
float (*deform_cos)[3]; /* coords of deformed mesh but without stroke displacement */
float (*deform_imats)[3][3]; /* crazyspace deformation matrices */
/* Partial redraw */
bool partial_redraw;
/* Used to cache the render of the active texture */
unsigned int texcache_side, *texcache, texcache_actual;
struct ImagePool *tex_pool;
/* Layer brush persistence between strokes */
float (*layer_co)[3]; /* Copy of the mesh vertices' locations */
@@ -197,6 +189,24 @@ typedef struct SculptSession {
struct StrokeCache *cache;
} SculptSession;
/* Session data (common) */
typedef struct PaintSession {
/* PBVH acceleration structure */
struct PBVH *pbvh;
/* Used to cache the render of the active texture */
unsigned int texcache_side, *texcache, texcache_actual;
struct ImagePool *tex_pool;
/* Partial redraw */
bool partial_redraw;
/* mode specific stuff */
SculptSession *sculpt;
} PaintSession;
void BKE_free_paintsession(struct Object *ob);
void BKE_free_sculptsession(struct Object *ob);
void BKE_free_sculptsession_deformMats(struct SculptSession *ss);
void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);

View File

@@ -62,7 +62,7 @@ typedef void (*BKE_pbvh_HitOccludedCallback)(PBVHNode *node, void *data, float *
PBVH *BKE_pbvh_new(void);
void BKE_pbvh_build_mesh(PBVH *bvh, struct MFace *faces, struct MVert *verts,
int totface, int totvert, struct CustomData *vdata);
int totface, int totvert, struct CustomData *vdata, struct CustomData *ldata);
void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
struct DMGridAdjacency *gridadj, int totgrid,
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
@@ -115,7 +115,7 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
int (*setMaterial)(int matnr, void *attribs), bool wireframe);
/* PBVH Access */
typedef enum {
typedef enum PBVHType {
PBVH_FACES,
PBVH_GRIDS,
PBVH_BMESH

View File

@@ -1515,8 +1515,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
const bool has_multires = (mmd && mmd->sculptlvl != 0);
bool multires_applied = false;
const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !useRenderParams;
const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !useRenderParams;
const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->paint && ob->paint->sculpt && !useRenderParams;
const bool sculpt_dyntopo = (sculpt_mode && ob->paint->sculpt->bm) && !useRenderParams;
const int draw_flag = dm_drawflag_calc(scene->toolsettings);
/* Generic preview only in object mode! */
@@ -2313,12 +2313,17 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask,
ob->derivedDeform->needsFree = 0;
ob->lastDataMask = dataMask;
if ((ob->mode & OB_MODE_SCULPT) && ob->sculpt) {
if ((ob->mode & OB_MODE_SCULPT) && ob->paint && ob->paint->sculpt) {
/* create PBVH immediately (would be created on the fly too,
* but this avoids waiting on first stroke) */
BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, false, false);
}
else if ((ob->mode & OB_MODE_VERTEX_PAINT) && ob->paint) {
/* needs to be called after we ensure tessface */
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
ob->paint->pbvh = dm->getPBVH(ob, dm);
}
BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS));
}

View File

@@ -222,23 +222,26 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
static bool check_sculpt_object_deformed(Object *object, bool for_construction)
{
SculptSession *ss = object->paint->sculpt;
bool deformed = false;
if (!ss)
return deformed;
/* Active modifiers means extra deformation, which can't be handled correct
* on birth of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
* stuff and show final DerivedMesh so user would see actual object shape.
*/
deformed |= object->sculpt->modifiers_active;
deformed |= ss->modifiers_active;
if (for_construction) {
deformed |= object->sculpt->kb != NULL;
deformed |= ss->kb != NULL;
}
else {
/* As in case with modifiers, we can't synchronize deformation made against
* PBVH and non-locked keyblock, so also use PBVH only for brushes and
* final DM to give final result to user.
*/
deformed |= object->sculpt->kb && (object->shapeflag & OB_SHAPE_LOCK) == 0;
deformed |= ss->kb && (object->shapeflag & OB_SHAPE_LOCK) == 0;
}
return deformed;
@@ -254,37 +257,40 @@ static bool can_pbvh_draw(Object *ob, DerivedMesh *dm)
return false;
}
return cddm->mvert == me->mvert || ob->sculpt->kb;
return cddm->mvert == me->mvert || (ob->paint->sculpt && ob->paint->sculpt->kb);
}
static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
SculptSession *ss;
if (!ob) {
cddm->pbvh = NULL;
return NULL;
}
if (!ob->sculpt)
if (!ob->paint)
return NULL;
if (ob->sculpt->pbvh) {
cddm->pbvh = ob->sculpt->pbvh;
if (ob->paint->pbvh) {
cddm->pbvh = ob->paint->pbvh;
cddm->pbvh_draw = can_pbvh_draw(ob, dm);
}
ss = ob->paint->sculpt;
/* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */
if (!cddm->pbvh && ob->sculpt->bm) {
if (!cddm->pbvh && ss && ss->bm) {
cddm->pbvh = BKE_pbvh_new();
cddm->pbvh_draw = true;
BKE_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
ob->sculpt->bm_smooth_shading,
ob->sculpt->bm_log, ob->sculpt->cd_vert_node_offset,
ob->sculpt->cd_face_node_offset);
BKE_pbvh_build_bmesh(cddm->pbvh, ss->bm,
ss->bm_smooth_shading,
ss->bm_log, ss->cd_vert_node_offset,
ss->cd_face_node_offset);
pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
pbvh_show_diffuse_color_set(cddm->pbvh, ss->show_diffuse_color);
}
@@ -301,11 +307,15 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
BKE_mesh_tessface_ensure(me);
BKE_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
me->totface, me->totvert, &me->vdata);
me->totface, me->totvert, &me->vdata, &me->ldata);
pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
if (ss) {
pbvh_show_diffuse_color_set(cddm->pbvh, ss->show_diffuse_color);
deformed = check_sculpt_object_deformed(ob, true);
deformed = check_sculpt_object_deformed(ob, true);
}
else
deformed = false;
if (deformed && ob->derivedDeform) {
DerivedMesh *deformdm = ob->derivedDeform;

View File

@@ -377,9 +377,9 @@ void multires_force_update(Object *ob)
if (ob) {
BKE_object_free_derived_caches(ob);
if (ob->sculpt && ob->sculpt->pbvh) {
BKE_pbvh_free(ob->sculpt->pbvh);
ob->sculpt->pbvh = NULL;
if (ob->paint && ob->paint->pbvh) {
BKE_pbvh_free(ob->paint->pbvh);
ob->paint->pbvh = NULL;
}
}
}

View File

@@ -434,7 +434,7 @@ void BKE_object_free_ex(Object *ob, bool do_id_user)
if (ob->bsoft) bsbFree(ob->bsoft);
if (ob->gpulamp.first) GPU_lamp_free(ob);
BKE_free_sculptsession(ob);
BKE_free_paintsession(ob);
if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
@@ -1523,7 +1523,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
BKE_constraints_copy(&obn->constraints, &ob->constraints, true);
obn->mode = OB_MODE_OBJECT;
obn->sculpt = NULL;
obn->paint = NULL;
/* increase user numbers */
id_us_plus((ID *)obn->data);
@@ -3232,25 +3232,26 @@ void BKE_object_handle_update(EvaluationContext *eval_ctx, Scene *scene, Object
void BKE_object_sculpt_modifiers_changed(Object *ob)
{
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession ? psession->sculpt : NULL;
if (ss) {
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
* the meantime .. weak */
if (ss->pbvh) {
BKE_pbvh_free(ss->pbvh);
ss->pbvh = NULL;
if (psession->pbvh) {
BKE_pbvh_free(psession->pbvh);
psession->pbvh = NULL;
}
BKE_free_sculptsession_deformMats(ob->sculpt);
BKE_free_sculptsession_deformMats(psession->sculpt);
}
else {
PBVHNode **nodes;
int n, totnode;
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
BKE_pbvh_search_gather(psession->pbvh, NULL, NULL, &nodes, &totnode);
for (n = 0; n < totnode; n++)
BKE_pbvh_node_mark_update(nodes[n]);

View File

@@ -573,7 +573,7 @@ void BKE_free_sculptsession_deformMats(SculptSession *ss)
/* Write out the sculpt dynamic-topology BMesh to the Mesh */
static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
{
SculptSession *ss = ob->sculpt;
SculptSession *ss = ob->paint->sculpt;
if (ss->bm) {
if (ob->data) {
@@ -591,7 +591,7 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
void BKE_sculptsession_bm_to_me(Object *ob, bool reorder)
{
if (ob && ob->sculpt) {
if (ob && ob->paint && ob->paint->sculpt) {
sculptsession_bm_to_me_update_data_only(ob, reorder);
/* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */
@@ -601,8 +601,11 @@ void BKE_sculptsession_bm_to_me(Object *ob, bool reorder)
void BKE_sculptsession_bm_to_me_for_render(Object *object)
{
if (object && object->sculpt) {
if (object->sculpt->bm) {
if (object && object->paint && object->paint->sculpt) {
PaintSession *psession = object->paint;
SculptSession *ss = psession->sculpt;
if (ss->bm) {
/* Ensure no points to old arrays are stored in DM
*
* Apparently, we could not use DAG_id_tag_update
@@ -611,9 +614,9 @@ 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;
if (psession->pbvh) {
BKE_pbvh_free(psession->pbvh);
psession->pbvh = NULL;
}
sculptsession_bm_to_me_update_data_only(object, false);
@@ -628,29 +631,18 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object)
void BKE_free_sculptsession(Object *ob)
{
if (ob && ob->sculpt) {
SculptSession *ss = ob->sculpt;
DerivedMesh *dm = ob->derivedFinal;
if (ob && ob->paint && ob->paint->sculpt) {
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
if (ss->bm) {
BKE_sculptsession_bm_to_me(ob, true);
BM_mesh_free(ss->bm);
}
if (ss->pbvh)
BKE_pbvh_free(ss->pbvh);
if (ss->bm_log)
BM_log_free(ss->bm_log);
if (dm && dm->getPBVH)
dm->getPBVH(NULL, dm); /* signal to clear */
if (ss->texcache)
MEM_freeN(ss->texcache);
if (ss->tex_pool)
BKE_image_pool_free(ss->tex_pool);
if (ss->layer_co)
MEM_freeN(ss->layer_co);
@@ -663,10 +655,37 @@ void BKE_free_sculptsession(Object *ob)
MEM_freeN(ss);
ob->sculpt = NULL;
psession->sculpt = NULL;
}
}
void BKE_free_paintsession(Object *ob) {
if (ob && ob->paint) {
PaintSession *psession = ob->paint;
DerivedMesh *dm = ob->derivedFinal;
if (psession->pbvh)
BKE_pbvh_free(psession->pbvh);
if (psession->texcache)
MEM_freeN(psession->texcache);
if (psession->tex_pool)
BKE_image_pool_free(psession->tex_pool);
if (dm && dm->getPBVH)
dm->getPBVH(NULL, dm); /* signal to clear */
if (psession->sculpt)
BKE_free_sculptsession(ob);
MEM_freeN(psession);
ob->paint = NULL;
}
}
/* Sculpt mode handles multires differently from regular meshes, but only if
* it's the last modifier on the stack and it is not on the first level */
MultiresModifierData *BKE_sculpt_multires_active(Scene *scene, Object *ob)
@@ -675,7 +694,7 @@ MultiresModifierData *BKE_sculpt_multires_active(Scene *scene, Object *ob)
ModifierData *md;
VirtualModifierData virtualModifierData;
if (ob->sculpt && ob->sculpt->bm) {
if (ob->paint && ob->paint->sculpt && ob->paint->sculpt->bm) {
/* can't combine multires and dynamic topology */
return NULL;
}
@@ -709,7 +728,7 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
VirtualModifierData virtualModifierData;
if (mmd || ob->sculpt->bm)
if (mmd || ob->paint->sculpt->bm)
return false;
/* non-locked shape keys could be handled in the same way as deformed mesh */
@@ -738,7 +757,8 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
bool need_pmap, bool need_mask)
{
DerivedMesh *dm;
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
Mesh *me = ob->data;
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
@@ -767,7 +787,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
}
/* BMESH ONLY --- at some point we should move sculpt code to use polygons only - but for now it needs tessfaces */
BKE_mesh_tessface_ensure(me);
//BKE_mesh_tessface_ensure(me);
if (!mmd) ss->kb = BKE_keyblock_from_object(ob);
else ss->kb = NULL;
@@ -795,10 +815,10 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK);
}
ss->pbvh = dm->getPBVH(ob, dm);
psession->pbvh = dm->getPBVH(ob, dm);
ss->pmap = (need_pmap && dm->getPolyMap) ? dm->getPolyMap(ob, dm) : NULL;
pbvh_show_diffuse_color_set(ss->pbvh, ss->show_diffuse_color);
pbvh_show_diffuse_color_set(psession->pbvh, ss->show_diffuse_color);
if (ss->modifiers_active) {
if (!ss->orig_cos) {
@@ -809,7 +829,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL);
BKE_crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
BKE_pbvh_apply_vertCos(psession->pbvh, ss->deform_cos);
for (a = 0; a < me->totvert; ++a) {
invert_m3(ss->deform_imats[a]);
@@ -826,14 +846,14 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
/* if pbvh is deformed, key block is already applied to it */
if (ss->kb) {
bool pbvh_deformd = BKE_pbvh_isDeformed(ss->pbvh);
bool pbvh_deformd = BKE_pbvh_isDeformed(psession->pbvh);
if (!pbvh_deformd || ss->deform_cos == NULL) {
float (*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
if (vertCos) {
if (!pbvh_deformd) {
/* apply shape keys coordinates to PBVH */
BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
BKE_pbvh_apply_vertCos(psession->pbvh, vertCos);
}
if (ss->deform_cos == NULL) {
ss->deform_cos = vertCos;

View File

@@ -533,7 +533,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
}
/* Do a full rebuild with on Mesh data structure */
void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata)
void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert, struct CustomData *vdata, CustomData *ldata)
{
BBC *prim_bbc = NULL;
BB cb;
@@ -546,7 +546,11 @@ void BKE_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int
bvh->totvert = totvert;
bvh->leaf_limit = LEAF_LIMIT;
bvh->vdata = vdata;
bvh->ldata = ldata;
if (bvh->ldata) {
bvh->drawtype |= PBVH_DRAW_NO_INDEXED;
}
BB_reset(&cb);
/* For each face, store the AABB and the AABB centroid */
@@ -1090,7 +1094,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
GPU_build_mesh_pbvh_buffers(node->face_vert_indices,
bvh->faces, bvh->verts,
node->prim_indices,
node->totprim);
node->totprim, (bvh->drawtype & PBVH_DRAW_NO_INDEXED) != 0);
break;
case PBVH_BMESH:
node->draw_buffers =
@@ -1121,6 +1125,8 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
node->face_verts,
CustomData_get_layer(bvh->vdata,
CD_PAINT_MASK),
CustomData_get_layer(bvh->ldata,
CD_MLOOPCOL),
node->face_vert_indices,
bvh->show_diffuse_color);
break;

View File

@@ -116,11 +116,18 @@ typedef enum {
PBVH_DYNTOPO_SMOOTH_SHADING = 1
} PBVHFlags;
/* don't use indexed drawing even if smooth shaded because we need to sample per face face data */
typedef enum {
PBVH_DRAW_NO_INDEXED = 1
} PBVHDraw;
typedef struct PBVHBMeshLog PBVHBMeshLog;
typedef enum PBVHType PBVHType;
struct PBVH {
PBVHType type;
PBVHFlags flags;
PBVHDraw drawtype;
PBVHNode *nodes;
int node_mem_count, totnode;
@@ -135,6 +142,7 @@ struct PBVH {
MVert *verts;
MFace *faces;
CustomData *vdata;
CustomData *ldata;
/* Grid Data */
CCGKey gridkey;

View File

@@ -3296,23 +3296,23 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
return NULL;
}
if (!ob->sculpt)
if (!ob->paint)
return NULL;
grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
if (ob->sculpt->pbvh) {
if (ob->paint->pbvh) {
if (grid_pbvh) {
/* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
* but this can be freed on ccgdm release, this updates the pointers
* when the ccgdm gets remade, the assumption is that the topology
* does not change. */
ccgdm_create_grids(dm);
BKE_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
BKE_pbvh_grids_update(ob->paint->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces,
ccgdm->gridFlagMats, ccgdm->gridHidden);
}
ccgdm->pbvh = ob->sculpt->pbvh;
ccgdm->pbvh = ob->paint->pbvh;
}
if (ccgdm->pbvh)
@@ -3326,20 +3326,21 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
numGrids = ccgDM_getNumGrids(dm);
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
ob->paint->pbvh = ccgdm->pbvh = BKE_pbvh_new();
BKE_pbvh_build_grids(ccgdm->pbvh, ccgdm->gridData, ccgdm->gridAdjacency,
numGrids, &key, (void **) ccgdm->gridFaces, ccgdm->gridFlagMats, ccgdm->gridHidden);
}
else if (ob->type == OB_MESH) {
Mesh *me = ob->data;
ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
void *ldata = (ob->mode & OB_MODE_VERTEX_PAINT) ? &me->ldata : NULL;
ob->paint->pbvh = ccgdm->pbvh = BKE_pbvh_new();
BLI_assert(!(me->mface == NULL && me->mpoly != NULL)); /* BMESH ONLY complain if mpoly is valid but not mface */
BKE_pbvh_build_mesh(ccgdm->pbvh, me->mface, me->mvert,
me->totface, me->totvert, &me->vdata);
me->totface, me->totvert, &me->vdata, ldata);
}
if (ccgdm->pbvh)
pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->sculpt->show_diffuse_color);
if (ccgdm->pbvh && ob->paint->sculpt)
pbvh_show_diffuse_color_set(ccgdm->pbvh, ob->paint->sculpt->show_diffuse_color);
return ccgdm->pbvh;
}

View File

@@ -5186,8 +5186,8 @@ static void direct_link_object(FileData *fd, Object *ob)
/* in case this value changes in future, clamp else we get undefined behavior */
CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
if (ob->sculpt) {
ob->sculpt = MEM_callocN(sizeof(SculptSession), "reload sculpt session");
if (ob->paint) {
ob->paint = MEM_callocN(sizeof(PaintSession), "reload paint session");
}
link_list(fd, &ob->lodlevels);

View File

@@ -1538,7 +1538,7 @@ static const char *object_mode_op_string(int mode)
if (mode == OB_MODE_SCULPT)
return "SCULPT_OT_sculptmode_toggle";
if (mode == OB_MODE_VERTEX_PAINT)
return "PAINT_OT_vertex_paint_toggle";
return "PAINT_OT_vertex_paint_pbvh_toggle";
if (mode == OB_MODE_WEIGHT_PAINT)
return "PAINT_OT_weight_paint_toggle";
if (mode == OB_MODE_TEXTURE_PAINT)

View File

@@ -52,6 +52,7 @@ set(SRC
paint_undo.c
paint_utils.c
paint_vertex.c
paint_vertex_pbvh.c
paint_vertex_proj.c
sculpt.c
sculpt_undo.c

View File

@@ -534,7 +534,7 @@ static bool sculpt_get_brush_geometry(
mouse[0] = x;
mouse[1] = y;
if (vc->obact->sculpt && vc->obact->sculpt->pbvh &&
if (vc->obact->paint && vc->obact->paint->pbvh &&
sculpt_stroke_get_location(C, location, mouse))
{
Brush *brush = BKE_paint_brush(paint);
@@ -1004,7 +1004,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* TODO: as sculpt and other paint modes are unified, this
* special mode of drawing will go away */
if ((mode == PAINT_SCULPT) && vc.obact->sculpt) {
if ((mode == PAINT_SCULPT) && vc.obact->paint->sculpt) {
float location[3];
int pixel_radius;
bool hit;

View File

@@ -384,7 +384,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
pbvh = dm->getPBVH(ob, dm);
ob->sculpt->pbvh = pbvh;
ob->paint->pbvh = pbvh;
get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
pbvh_type = BKE_pbvh_type(pbvh);

View File

@@ -121,6 +121,9 @@ void PAINT_OT_weight_gradient(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint_pbvh_toggle(struct wmOperatorType *ot);
void PAINT_OT_vertex_paint_pbvh(struct wmOperatorType *ot);
unsigned int vpaint_get_current_col(struct Scene *scene, struct VPaint *vp);
@@ -219,6 +222,7 @@ void paint_get_tex_pixel_col(struct MTex *mtex, float u, float v, float rgba[4],
void paint_sample_color(bContext *C, struct ARegion *ar, int x, int y, bool texpaint_proj, bool palette);
void paint_stroke_operator_properties(struct wmOperatorType *ot);
float paint_pbvh_raycast_init(struct ViewContext *vc, const float mouse[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original);
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);

View File

@@ -108,7 +108,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
value = RNA_float_get(op->ptr, "value");
BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
pbvh = ob->sculpt->pbvh;
pbvh = ob->paint->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
@@ -216,7 +216,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
negate_m4(clip_planes);
BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
pbvh = ob->sculpt->pbvh;
pbvh = ob->paint->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
sculpt_undo_push_begin("Mask box fill");
@@ -362,7 +362,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
negate_m4(clip_planes);
BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
pbvh = ob->sculpt->pbvh;
pbvh = ob->paint->pbvh;
multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
sculpt_undo_push_begin("Mask lasso fill");

View File

@@ -1111,7 +1111,9 @@ void ED_operatortypes_paint(void)
/* vertex */
WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
WM_operatortype_append(PAINT_OT_vertex_paint_pbvh_toggle);
WM_operatortype_append(PAINT_OT_vertex_paint);
WM_operatortype_append(PAINT_OT_vertex_paint_pbvh);
WM_operatortype_append(PAINT_OT_vertex_color_set);
WM_operatortype_append(PAINT_OT_vertex_color_smooth);

View File

@@ -54,6 +54,7 @@
#include "BKE_image.h"
#include "BKE_material.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_report.h"
#include "RNA_access.h"
@@ -225,6 +226,35 @@ void paint_stroke_operator_properties(wmOperatorType *ot)
}
float paint_pbvh_raycast_init(ViewContext *vc, const float mouse[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original)
{
float obimat[4][4];
float dist;
Object *ob = vc->obact;
RegionView3D *rv3d = vc->ar->regiondata;
/* TODO: what if the segment is totally clipped? (return == 0) */
ED_view3d_win_to_segment(vc->ar, vc->v3d, mouse, ray_start, ray_end, true);
invert_m4_m4(obimat, ob->obmat);
mul_m4_v3(obimat, ray_start);
mul_m4_v3(obimat, ray_end);
sub_v3_v3v3(ray_normal, ray_end, ray_start);
dist = normalize_v3(ray_normal);
if (!rv3d->is_persp) {
BKE_pbvh_raycast_project_ray_root(ob->paint->pbvh, original, ray_start, ray_end, ray_normal);
/* recalculate the normal */
sub_v3_v3v3(ray_normal, ray_end, ray_start);
dist = normalize_v3(ray_normal);
}
return dist;
}
/* 3D Paint */
static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])

View File

@@ -0,0 +1,393 @@
/*
* ***** 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: all of this file.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/sculpt_paint/paint_vertex_pbvh.c
* \ingroup edsculpt
*/
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_bitmap.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "DNA_armature_types.h"
#include "DNA_mesh_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_object_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "BKE_DerivedMesh.h"
#include "BKE_action.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_report.h"
#include "BKE_colortools.h"
#include "WM_api.h"
#include "WM_types.h"
#include "GPU_buffers.h"
#include "ED_armature.h"
#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "paint_intern.h"
typedef struct {
PaintSession *psession;
const float *ray_start, *ray_normal;
bool hit;
float dist;
} VPaintRaycastData;
static void vpaint_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
{
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
VPaintRaycastData *vrd = data_v;
if (BKE_pbvh_node_raycast(vrd->psession->pbvh, node, NULL, false,
vrd->ray_start, vrd->ray_normal, &vrd->dist))
{
vrd->hit = 1;
*tmin = vrd->dist;
}
}
}
static bool vpaint_stroke_get_location(bContext *C, float out[3], const float mouse[2])
{
Object *ob;
PaintSession *psession;
float ray_start[3], ray_end[3], ray_normal[3], dist;
VPaintRaycastData vrd;
ViewContext vc;
view3d_set_viewcontext(C, &vc);
ob = vc.obact;
psession = ob->paint;
//sculpt_stroke_modifiers_check(C, ob);
dist = paint_pbvh_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, false);
vrd.psession = psession;
vrd.hit = 0;
vrd.ray_start = ray_start;
vrd.ray_normal = ray_normal;
vrd.dist = dist;
BKE_pbvh_raycast(psession->pbvh, vpaint_raycast_cb, &vrd,
ray_start, ray_normal, false);
copy_v3_v3(out, ray_normal);
mul_v3_fl(out, vrd.dist);
add_v3_v3(out, ray_start);
return vrd.hit;
}
static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *UNUSED(op),
const float mouse[2])
{
float co[3];
/* Don't start the stroke until mouse goes over the mesh.
* note: mouse will only be null when re-executing the saved stroke. */
if (!mouse || vpaint_stroke_get_location(C, co, mouse)) {
Object *ob = CTX_data_active_object(C);
ED_view3d_init_mats_rv3d(ob, CTX_wm_region_view3d(C));
// sculpt_update_cache_invariants(C, sd, psession, op, mouse);
// sculpt_undo_push_begin(sculpt_tool_name(sd));
return 1;
}
else
return 0;
}
static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int retval;
// op->customdata = paint_stroke_new(C, op, NULL, vpaint_stroke_test_start,
// vpaint_stroke_update_step, NULL,
// vpaint_stroke_done, event->type);
(void)vpaint_stroke_test_start;
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
paint_stroke_data_free(op);
return OPERATOR_FINISHED;
}
/* add modal handler */
WM_event_add_modal_handler(C, op);
OPERATOR_RETVAL_CHECK(retval);
BLI_assert(retval == OPERATOR_RUNNING_MODAL);
return OPERATOR_RUNNING_MODAL;
}
void PAINT_OT_vertex_paint_pbvh(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Vertex Paint";
ot->idname = "PAINT_OT_vertex_paint_pbvh";
ot->description = "Paint a stroke in the active vertex color layer";
/* api callbacks */
ot->invoke = vpaint_invoke;
ot->modal = paint_stroke_modal;
// ot->exec = vpaint_exec;
ot->poll = vertex_paint_poll;
// ot->cancel = vpaint_cancel;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
paint_stroke_operator_properties(ot);
}
/* 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);
}
}
}
static bool make_vertexcol(Object *ob) /* single ob */
{
Mesh *me;
if ((ob->id.lib) ||
((me = BKE_mesh_from_object(ob)) == NULL) ||
(me->totpoly == 0) ||
(me->edit_btmesh))
{
return false;
}
/* copies from shadedisplist to mcol */
if (!me->mloopcol && me->totloop) {
if (!me->mcol) {
CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
}
if (!me->mloopcol) {
CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop);
}
BKE_mesh_update_customdata_pointers(me, true);
}
update_tessface_data(ob, me);
DAG_id_tag_update(&me->id, 0);
return (me->mloopcol != NULL);
}
static void vpaint_init_session(Scene *scene, Object *ob)
{
PaintSession *psession = ob->paint;
/* needs to be called after we ensure tessface */
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
if (!psession) {
psession = ob->paint = MEM_callocN(sizeof(PaintSession), "sculpt session");
}
psession->pbvh = dm->getPBVH(ob, dm);
// BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, 0, false);
}
static VPaint *new_vpaint(int wpaint)
{
VPaint *vp = MEM_callocN(sizeof(VPaint), "VPaint");
vp->flag = (wpaint) ? 0 : VP_SPRAY;
vp->paint.flags |= PAINT_SHOW_BRUSH;
return vp;
}
static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
const int mode_flag = OB_MODE_VERTEX_PAINT;
const bool is_mode_set = (ob->mode & mode_flag) != 0;
Scene *scene = CTX_data_scene(C);
VPaint *vp = scene->toolsettings->vpaint;
Mesh *me;
MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
int flush_recalc = 0;
if (!is_mode_set) {
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
return OPERATOR_CANCELLED;
}
}
/* multires in sculpt mode could have different from object mode subdivision level */
flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl;
me = BKE_mesh_from_object(ob);
/* toggle: end vpaint */
if (is_mode_set) {
ob->mode &= ~mode_flag;
if (mmd)
multires_force_update(ob);
if (flush_recalc)
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
BKE_mesh_flush_select_from_polys(me);
}
BKE_free_paintsession(ob);
paint_cursor_delete_textures();
}
else {
ob->mode |= mode_flag;
if (me->mloopcol == NULL) {
make_vertexcol(ob);
}
if (vp == NULL) {
vp = scene->toolsettings->vpaint = new_vpaint(0);
/* Turn on X plane mirror symmetry by default */
vp->paint.symmetry_flags |= PAINT_SYMM_X;
vp->paint.flags |= PAINT_SHOW_BRUSH;
}
/* Create sculpt mode session data */
if (ob->paint)
BKE_free_paintsession(ob);
vpaint_init_session(scene, ob);
paint_cursor_start(C, vertex_paint_poll);
BKE_paint_init(&scene->toolsettings->unified_paint_settings, &vp->paint, PAINT_CURSOR_VERTEX_PAINT);
}
/* update modifier stack for mapping requirements */
DAG_id_tag_update(&me->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
return OPERATOR_FINISHED;
}
/* for switching to/from mode */
static int paint_poll_test(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob == NULL || ob->type != OB_MESH)
return 0;
if (!ob->data || ((ID *)ob->data)->lib)
return 0;
if (CTX_data_edit_object(C))
return 0;
return 1;
}
void PAINT_OT_vertex_paint_pbvh_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Vertex Paint Mode";
ot->idname = "PAINT_OT_vertex_paint_pbvh_toggle";
ot->description = "Toggle the vertex paint mode in 3D view";
/* api callbacks */
ot->exec = vpaint_mode_toggle_exec;
ot->poll = paint_poll_test;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}

File diff suppressed because it is too large Load Diff

View File

@@ -61,7 +61,7 @@ int sculpt_poll_view3d(struct bContext *C);
bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]);
/* Dynamic topology */
void sculpt_pbvh_clear(Object *ob);
void paint_pbvh_clear(Object *ob);
void sculpt_dyntopo_node_layers_add(struct SculptSession *ss);
void sculpt_update_after_dynamic_topology_toggle(bContext *C);
void sculpt_dynamic_topology_enable(struct bContext *C);

View File

@@ -97,7 +97,8 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
Scene *scene = CTX_data_scene(C);
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
SculptSession *ss = ob->paint->sculpt;
PaintSession *psession = ob->paint;
MVert *mvert;
int *index, i, j;
@@ -144,7 +145,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
BKE_pbvh_apply_vertCos(psession->pbvh, vertCos);
MEM_freeN(vertCos);
}
@@ -188,7 +189,7 @@ static int sculpt_undo_restore_hidden(bContext *C, DerivedMesh *dm,
SculptUndoNode *unode)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
SculptSession *ss = ob->paint->sculpt;
int i;
if (unode->maxvert) {
@@ -225,7 +226,7 @@ static int sculpt_undo_restore_hidden(bContext *C, DerivedMesh *dm,
static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode *unode)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
SculptSession *ss = ob->paint->sculpt;
MVert *mvert;
float *vmask;
int *index, i, j;
@@ -268,7 +269,8 @@ static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode
static void sculpt_undo_bmesh_restore_generic(bContext *C,
SculptUndoNode *unode,
Object *ob,
SculptSession *ss)
SculptSession *ss,
PaintSession *psession)
{
if (unode->applied) {
BM_log_undo(ss->bm, ss->bm_log);
@@ -289,7 +291,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
(void)C;
#endif
BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
BKE_pbvh_search_gather(psession->pbvh, NULL, NULL, &nodes, &totnode);
#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
for (i = 0; i < totnode; i++) {
@@ -300,7 +302,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
MEM_freeN(nodes);
}
else {
sculpt_pbvh_clear(ob);
paint_pbvh_clear(ob);
}
}
@@ -308,10 +310,10 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
static void sculpt_undo_bmesh_enable(Object *ob,
SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
SculptSession *ss = ob->paint->sculpt;
Mesh *me = ob->data;
sculpt_pbvh_clear(ob);
paint_pbvh_clear(ob);
/* Create empty BMesh and enable logging */
ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
@@ -370,7 +372,7 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
static int sculpt_undo_bmesh_restore(bContext *C,
SculptUndoNode *unode,
Object *ob,
SculptSession *ss)
SculptSession *ss, PaintSession *psession)
{
switch (unode->type) {
case SCULPT_UNDO_DYNTOPO_BEGIN:
@@ -383,7 +385,7 @@ static int sculpt_undo_bmesh_restore(bContext *C,
default:
if (ss->bm_log) {
sculpt_undo_bmesh_restore_generic(C, unode, ob, ss);
sculpt_undo_bmesh_restore_generic(C, unode, ob, ss, psession);
return true;
}
break;
@@ -398,7 +400,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob = CTX_data_active_object(C);
DerivedMesh *dm;
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
SculptUndoNode *unode;
bool update = false, rebuild = false;
bool need_mask = false;
@@ -419,7 +422,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
/* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
dm = mesh_get_derived_final(scene, ob, 0);
if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss, psession))
return;
for (unode = lb->first; unode; unode = unode->next) {
@@ -467,8 +470,8 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb)
/* we update all nodes still, should be more clever, but also
* needs to work correct when exiting/entering sculpt mode and
* the nodes get recreated, though in that case it could do all */
BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild);
BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
BKE_pbvh_search_callback(psession->pbvh, NULL, NULL, update_cb, &rebuild);
BKE_pbvh_update(psession->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL);
if (BKE_sculpt_multires_active(scene, ob)) {
if (rebuild)
@@ -599,7 +602,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
SculptUndoNode *unode;
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
int totvert, allvert, totgrid, maxgrid, gridsize, *grids;
unode = MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode");
@@ -608,8 +612,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
unode->node = node;
if (node) {
BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert);
BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
BKE_pbvh_node_num_verts(psession->pbvh, node, &totvert, &allvert);
BKE_pbvh_node_get_grids(psession->pbvh, node, &grids, &totgrid,
&maxgrid, &gridsize, NULL, NULL);
unode->totvert = totvert;
@@ -631,7 +635,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
break;
case SCULPT_UNDO_HIDDEN:
if (maxgrid)
sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode);
sculpt_undo_alloc_and_store_hidden(psession->pbvh, unode);
else
unode->vert_hidden = BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden");
@@ -670,10 +674,11 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node,
static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
BKE_pbvh_vertex_iter_begin(psession->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
copy_v3_v3(unode->co[vd.i], vd.co);
if (vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no);
@@ -687,7 +692,7 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
{
PBVH *pbvh = ob->sculpt->pbvh;
PBVH *pbvh = ob->paint->pbvh;
PBVHNode *node = unode->node;
if (unode->grids) {
@@ -709,10 +714,10 @@ static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL)
BKE_pbvh_vertex_iter_begin(psession->pbvh, unode->node, vd, PBVH_ITER_ALL)
{
unode->mask[vd.i] = *vd.mask;
}
@@ -725,7 +730,8 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
{
ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH);
SculptUndoNode *unode = lb->first;
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
PBVHVertexIter vd;
if (!lb->first) {
@@ -776,7 +782,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
case SCULPT_UNDO_MASK:
/* Before any vertex values get modified, ensure their
* original positions are logged */
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
BKE_pbvh_vertex_iter_begin(psession->pbvh, node, vd, PBVH_ITER_ALL) {
BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset);
}
BKE_pbvh_vertex_iter_end;
@@ -786,7 +792,7 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
{
GSetIterator gs_iter;
GSet *faces = BKE_pbvh_bmesh_node_faces(node);
BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
BKE_pbvh_vertex_iter_begin(psession->pbvh, node, vd, PBVH_ITER_ALL) {
BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset);
}
BKE_pbvh_vertex_iter_end;
@@ -811,7 +817,8 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
SculptUndoType type)
{
SculptSession *ss = ob->sculpt;
PaintSession *psession = ob->paint;
SculptSession *ss = psession->sculpt;
SculptUndoNode *unode;
/* list is manipulated by multiple threads, so we lock */
@@ -841,14 +848,14 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node,
if (unode->grids) {
int totgrid, *grids;
BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid,
BKE_pbvh_node_get_grids(psession->pbvh, node, &grids, &totgrid,
NULL, NULL, NULL, NULL);
memcpy(unode->grids, grids, sizeof(int) * totgrid);
}
else {
int *vert_indices, allvert;
BKE_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert);
BKE_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL);
BKE_pbvh_node_num_verts(psession->pbvh, node, NULL, &allvert);
BKE_pbvh_node_get_verts(psession->pbvh, node, &vert_indices, NULL);
memcpy(unode->index, vert_indices, sizeof(int) * unode->totvert);
}

View File

@@ -263,8 +263,8 @@ static void stats_object_pose(Object *ob, SceneStats *stats)
static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
{
stats->totvert = ob->sculpt->bm->totvert;
stats->tottri = ob->sculpt->bm->totface;
stats->totvert = ob->paint->sculpt->bm->totvert;
stats->tottri = ob->paint->sculpt->bm->totface;
}
static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
@@ -338,7 +338,7 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
static bool stats_is_object_dynamic_topology_sculpt(Object *ob)
{
return (ob && (ob->mode & OB_MODE_SCULPT) &&
ob->sculpt && ob->sculpt->bm);
ob->paint && ob->paint->sculpt && ob->paint->sculpt->bm);
}
/* Statistics displayed in info header. Called regularly on scene changes. */

View File

@@ -3754,17 +3754,17 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) {
if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->paint && ob->paint->sculpt && (p = BKE_paint_get_active(scene))) {
GPUVertexAttribs gattribs;
float planes[4][4];
float (*fpl)[4] = NULL;
const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
if (ob->sculpt->partial_redraw) {
if (ob->paint->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
ob->paint->partial_redraw = false;
}
}
@@ -3811,7 +3811,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
(base->flag & SELECT) &&
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
(!ob->paint || !ob->paint->sculpt))
{
draw_mesh_object_outline(v3d, ob, dm);
}
@@ -3843,7 +3843,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) &&
(base->flag & SELECT) &&
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
(!ob->paint || !ob->paint->sculpt))
{
draw_mesh_object_outline(v3d, ob, dm);
}
@@ -3853,16 +3853,16 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glEnable(GL_LIGHTING);
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
if (ob->sculpt && (p = BKE_paint_get_active(scene))) {
if (ob->paint && ob->paint->sculpt && (p = BKE_paint_get_active(scene))) {
float planes[4][4];
float (*fpl)[4] = NULL;
const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
if (ob->sculpt->partial_redraw) {
if (ob->paint->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
ob->paint->partial_redraw = false;
}
}
@@ -3878,7 +3878,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
if ((!ob->paint || !ob->paint->sculpt) && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
glColor3ubv(ob_wire_col);
}
@@ -7415,7 +7415,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
dt = OB_SOLID;
}
if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
dt = OB_PAINT;
}

View File

@@ -165,7 +165,7 @@ typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
/* build */
GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
struct MFace *mface, struct MVert *mvert,
int *face_indices, int totface);
int *face_indices, int totface, bool no_indexed);
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
unsigned int **grid_hidden, int gridsize);
@@ -175,7 +175,7 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading);
/* update */
void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
int *vert_indices, int totvert, const float *vmask,
int *vert_indices, int totvert, const float *vmask, const int *lcol,
int (*face_vert_indices)[4], bool show_diffuse_color);
void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,

View File

@@ -1577,7 +1577,7 @@ static void gpu_color_from_mask_quad_set(const CCGKey *key,
}
void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
int *vert_indices, int totvert, const float *vmask,
int *vert_indices, int totvert, const float *vmask, const int *lcol,
int (*face_vert_indices)[4], bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
@@ -1627,7 +1627,11 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \
if (vmask) \
gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \
else \
else if (lcol) { \
char *lc = (char *)(lcol + vertex); \
copy_v3_v3_char((char *)out->color, lc); \
printf("updating vcol\n"); \
} else \
rgb_float_to_uchar(out->color, diffuse_color); \
} (void)0
@@ -1692,9 +1696,13 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
if (vmask)
gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
else
if (lcol) {
char *lc = (char *)(lcol + fv[vi[j][k]]);
copy_v3_v3_char((char *)out->color, lc);
printf("updating vcol\n");
} else
rgb_float_to_uchar(out->color, diffuse_color);
vert_data++;
}
}
@@ -1717,7 +1725,7 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
MFace *mface, MVert *mvert,
int *face_indices,
int totface)
int totface, bool no_indexed)
{
GPU_PBVH_Buffers *buffers;
unsigned short *tri_data;
@@ -1725,7 +1733,7 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
buffers->index_type = GL_UNSIGNED_SHORT;
buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH;
buffers->smooth = (mface[face_indices[0]].flag & ME_SMOOTH) && !no_indexed;
buffers->show_diffuse_color = false;
buffers->use_matcaps = false;

View File

@@ -117,7 +117,7 @@ typedef struct Object {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
struct SculptSession *sculpt;
struct PaintSession *paint;
short type, partype;
int par1, par2, par3; /* can be vertexnrs */

View File

@@ -1502,8 +1502,8 @@ int rna_DupliObject_index_get(PointerRNA *ptr)
int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
{
SculptSession *ss = ((Object *)ptr->id.data)->sculpt;
return (ss && ss->bm);
PaintSession *psession = ((Object *)ptr->id.data)->paint;
return (psession && psession && psession->sculpt->bm);
}
static void rna_Object_lod_distance_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)

View File

@@ -233,9 +233,9 @@ static void rna_Sculpt_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNU
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
if (ob->sculpt) {
ob->sculpt->bm_smooth_shading = ((scene->toolsettings->sculpt->flags &
SCULPT_DYNTOPO_SMOOTH_SHADING) != 0);
if (ob->paint && ob->paint->sculpt) {
ob->paint->sculpt->bm_smooth_shading = ((scene->toolsettings->sculpt->flags &
SCULPT_DYNTOPO_SMOOTH_SHADING) != 0);
}
}
}
@@ -244,12 +244,12 @@ static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene
{
Object *ob = (scene->basact) ? scene->basact->object : NULL;
if (ob && ob->sculpt) {
if (ob && ob->paint && ob->paint->sculpt) {
Sculpt *sd = scene->toolsettings->sculpt;
ob->sculpt->show_diffuse_color = ((sd->flags & SCULPT_SHOW_DIFFUSE) != 0);
ob->paint->sculpt->show_diffuse_color = ((sd->flags & SCULPT_SHOW_DIFFUSE) != 0);
if (ob->sculpt->pbvh)
pbvh_show_diffuse_color_set(ob->sculpt->pbvh, ob->sculpt->show_diffuse_color);
if (ob->paint->pbvh)
pbvh_show_diffuse_color_set(ob->paint->pbvh, ob->paint->sculpt->show_diffuse_color);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
}