Moved the PBVH from sculpt session to DerivedMesh/CDDM.
* Multires sculpting appears to work now * PBVH gets recalculated in some cases where it shouldn't, haven't looked into this yet
This commit is contained in:
parent
93beb0b85a
commit
243c73e96e
|
@ -59,6 +59,8 @@ struct MCol;
|
|||
struct ColorBand;
|
||||
struct GPUVertexAttribs;
|
||||
struct GPUDrawObject;
|
||||
struct ListBase;
|
||||
struct PBVH;
|
||||
|
||||
/* number of sub-elements each mesh element has (for interpolation) */
|
||||
#define SUB_ELEMS_VERT 0
|
||||
|
@ -73,6 +75,7 @@ struct DerivedMesh {
|
|||
int needsFree; /* checked on ->release, is set to 0 for cached results */
|
||||
int deformedOnly; /* set by modifier stack if only deformed from original */
|
||||
BVHCache bvhCache;
|
||||
|
||||
struct GPUDrawObject *drawObject;
|
||||
|
||||
/* Misc. Queries */
|
||||
|
@ -180,6 +183,14 @@ struct DerivedMesh {
|
|||
/* Get vertex normal, undefined if index is not valid */
|
||||
void (*getVertNo)(DerivedMesh *dm, int index, float no_r[3]);
|
||||
|
||||
/* Get a map of vertices to faces
|
||||
*/
|
||||
struct ListBase *(*getFaceMap)(DerivedMesh *dm);
|
||||
|
||||
/* Get the BVH used for paint modes
|
||||
*/
|
||||
struct PBVH *(*getPBVH)(DerivedMesh *dm);
|
||||
|
||||
/* Drawing Operations */
|
||||
|
||||
/* Draw all vertices as bgl points (no options) */
|
||||
|
@ -204,7 +215,7 @@ struct DerivedMesh {
|
|||
*
|
||||
* Also called for *final* editmode DerivedMeshes
|
||||
*/
|
||||
void (*drawFacesSolid)(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4],
|
||||
void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4],
|
||||
int (*setMaterial)(int, void *attribs));
|
||||
|
||||
/* Draw all faces
|
||||
|
|
|
@ -69,17 +69,15 @@ typedef struct SculptSession {
|
|||
struct MFace *mface;
|
||||
int totvert, totface;
|
||||
float *face_normals;
|
||||
struct PBVH *tree;
|
||||
|
||||
/* Mesh connectivity */
|
||||
struct ListBase *fmap;
|
||||
struct IndexNode *fmap_mem;
|
||||
int fmap_size;
|
||||
|
||||
/* Used temporarily per-stroke */
|
||||
float *vertexcosnos;
|
||||
|
||||
/* Partial redraw */
|
||||
struct PBVH *tree;
|
||||
int partial_redraw;
|
||||
|
||||
/* Used to cache the render of the active texture */
|
||||
|
|
|
@ -77,6 +77,12 @@ typedef struct {
|
|||
MVert *mvert;
|
||||
MEdge *medge;
|
||||
MFace *mface;
|
||||
|
||||
/* Cached */
|
||||
struct PBVH *pbvh;
|
||||
/* Mesh connectivity */
|
||||
struct ListBase *fmap;
|
||||
struct IndexNode *fmap_mem;
|
||||
} CDDerivedMesh;
|
||||
|
||||
/**************** DerivedMesh interface functions ****************/
|
||||
|
@ -171,6 +177,82 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
|
|||
no_r[2] = no[2]/32767.f;
|
||||
}
|
||||
|
||||
/* Updates all the face and vertex normals in a node
|
||||
|
||||
Note: the correctness of some vertex normals will be a little
|
||||
off, not sure if this will be noticeable or not */
|
||||
static void update_node_normals(const int *face_indices,
|
||||
const int *vert_indices,
|
||||
int totface, int totvert, void *data)
|
||||
{
|
||||
DerivedMesh *dm = data;
|
||||
CDDerivedMesh *cddm = data;
|
||||
float (*face_nors)[3];
|
||||
int i;
|
||||
|
||||
/* make a face normal layer if not present */
|
||||
face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
|
||||
if(!face_nors)
|
||||
face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
|
||||
NULL, dm->numFaceData);
|
||||
|
||||
/* Update face normals */
|
||||
for(i = 0; i < totface; ++i) {
|
||||
MFace *f = cddm->mface + face_indices[i];
|
||||
float *fn = face_nors[face_indices[i]];
|
||||
|
||||
if(f->v4)
|
||||
CalcNormFloat4(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co,
|
||||
cddm->mvert[f->v3].co, cddm->mvert[f->v4].co, fn);
|
||||
else
|
||||
CalcNormFloat(cddm->mvert[f->v1].co, cddm->mvert[f->v2].co,
|
||||
cddm->mvert[f->v3].co, fn);
|
||||
}
|
||||
|
||||
/* Update vertex normals */
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
const int v = vert_indices[i];
|
||||
float no[3] = {0,0,0};
|
||||
IndexNode *face;
|
||||
|
||||
for(face = cddm->fmap[v].first; face; face = face->next)
|
||||
VecAddf(no, no, face_nors[face->index]);
|
||||
|
||||
Normalize(no);
|
||||
|
||||
cddm->mvert[v].no[0] = no[0] * 32767;
|
||||
cddm->mvert[v].no[1] = no[1] * 32767;
|
||||
cddm->mvert[v].no[2] = no[2] * 32767;
|
||||
}
|
||||
}
|
||||
|
||||
static ListBase *cdDM_getFaceMap(DerivedMesh *dm)
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
|
||||
|
||||
if(!cddm->fmap) {
|
||||
create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, cddm->mface,
|
||||
dm->getNumVerts(dm), dm->getNumFaces(dm));
|
||||
printf("rebuild fmap\n");
|
||||
}
|
||||
|
||||
return cddm->fmap;
|
||||
}
|
||||
|
||||
static struct PBVH *cdDM_getPBVH(DerivedMesh *dm)
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
|
||||
|
||||
if(!cddm->pbvh) {
|
||||
cddm->pbvh = BLI_pbvh_new(update_node_normals, cddm);
|
||||
BLI_pbvh_build(cddm->pbvh, cddm->mface, cddm->mvert,
|
||||
dm->getNumFaces(dm), dm->getNumVerts(dm));
|
||||
printf("rebuild pbvh\n");
|
||||
}
|
||||
|
||||
return cddm->pbvh;
|
||||
}
|
||||
|
||||
static void cdDM_drawVerts(DerivedMesh *dm)
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
|
||||
|
@ -419,7 +501,7 @@ int planes_contain_AABB(float bb_min[3], float bb_max[3], void *data)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void cdDM_drawFacesSolid(DerivedMesh *dm, void *tree,
|
||||
static void cdDM_drawFacesSolid(DerivedMesh *dm,
|
||||
float (*partial_redraw_planes)[4],
|
||||
int (*setMaterial)(int, void *attribs))
|
||||
{
|
||||
|
@ -437,19 +519,19 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, void *tree,
|
|||
glVertex3fv(mvert[index].co); \
|
||||
}
|
||||
|
||||
if(tree) {
|
||||
BLI_pbvh_search(tree, BLI_pbvh_update_search_cb,
|
||||
if(cddm->pbvh) {
|
||||
BLI_pbvh_search(cddm->pbvh, BLI_pbvh_update_search_cb,
|
||||
PBVH_NodeData, NULL, NULL,
|
||||
PBVH_SEARCH_UPDATE);
|
||||
|
||||
if(partial_redraw_planes) {
|
||||
BLI_pbvh_search(tree, planes_contain_AABB,
|
||||
BLI_pbvh_search(cddm->pbvh, planes_contain_AABB,
|
||||
partial_redraw_planes,
|
||||
draw_partial_cb, PBVH_DrawData,
|
||||
PBVH_SEARCH_MODIFIED);
|
||||
}
|
||||
else {
|
||||
BLI_pbvh_search(tree, find_all, NULL,
|
||||
BLI_pbvh_search(cddm->pbvh, find_all, NULL,
|
||||
draw_partial_cb, PBVH_DrawData,
|
||||
PBVH_SEARCH_NORMAL);
|
||||
|
||||
|
@ -1376,12 +1458,21 @@ static void cdDM_foreachMappedFaceCenter(
|
|||
}
|
||||
}
|
||||
|
||||
static void cdDM_free_internal(CDDerivedMesh *cddm)
|
||||
{
|
||||
if(cddm->pbvh) BLI_pbvh_free(cddm->pbvh);
|
||||
if(cddm->fmap) MEM_freeN(cddm->fmap);
|
||||
if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
|
||||
}
|
||||
|
||||
static void cdDM_release(DerivedMesh *dm)
|
||||
{
|
||||
CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
|
||||
|
||||
if (DM_release(dm))
|
||||
if (DM_release(dm)) {
|
||||
cdDM_free_internal(cddm);
|
||||
MEM_freeN(cddm);
|
||||
}
|
||||
}
|
||||
|
||||
/**************** CDDM interface functions ****************/
|
||||
|
@ -1416,6 +1507,9 @@ static CDDerivedMesh *cdDM_create(const char *desc)
|
|||
dm->getVertCo = cdDM_getVertCo;
|
||||
dm->getVertNo = cdDM_getVertNo;
|
||||
|
||||
dm->getPBVH = cdDM_getPBVH;
|
||||
dm->getFaceMap = cdDM_getFaceMap;
|
||||
|
||||
dm->drawVerts = cdDM_drawVerts;
|
||||
|
||||
dm->drawUVEdges = cdDM_drawUVEdges;
|
||||
|
@ -1901,6 +1995,7 @@ static void MultiresDM_release(DerivedMesh *dm)
|
|||
}
|
||||
|
||||
if(DM_release(dm)) {
|
||||
cdDM_free_internal(&mrdm->cddm);
|
||||
MEM_freeN(mrdm->subco);
|
||||
MEM_freeN(mrdm->orco);
|
||||
if(mrdm->vert_face_map)
|
||||
|
|
|
@ -72,8 +72,6 @@
|
|||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_editVert.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_pbvh.h"
|
||||
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
|
@ -231,12 +229,6 @@ void free_sculptsession(SculptSession **ssp)
|
|||
if(ssp && *ssp) {
|
||||
SculptSession *ss = *ssp;
|
||||
|
||||
if(ss->fmap)
|
||||
MEM_freeN(ss->fmap);
|
||||
|
||||
if(ss->fmap_mem)
|
||||
MEM_freeN(ss->fmap_mem);
|
||||
|
||||
if(ss->texcache)
|
||||
MEM_freeN(ss->texcache);
|
||||
|
||||
|
@ -246,9 +238,6 @@ void free_sculptsession(SculptSession **ssp)
|
|||
if(ss->mesh_co_orig)
|
||||
MEM_freeN(ss->mesh_co_orig);
|
||||
|
||||
if(ss->tree)
|
||||
BLI_pbvh_free(ss->tree);
|
||||
|
||||
if(ss->face_normals)
|
||||
MEM_freeN(ss->face_normals);
|
||||
|
||||
|
|
|
@ -1615,7 +1615,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
|
|||
}
|
||||
|
||||
/* Only used by non-editmesh types */
|
||||
static void ccgDM_drawFacesSolid(DerivedMesh *dm, void *tree, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) {
|
||||
static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], int (*setMaterial)(int, void *attribs)) {
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
|
||||
|
|
|
@ -193,57 +193,6 @@ static void projectf(bglMats *mats, const float v[3], float p[2])
|
|||
|
||||
/*** BVH Tree ***/
|
||||
|
||||
/* Updates all the face and vertex normals in a node
|
||||
|
||||
Note: the correctness of some vertex normals will be a little
|
||||
off, not sure if this will be noticeable or not */
|
||||
static void sculpt_update_normals(const int *face_indices,
|
||||
const int *vert_indices,
|
||||
int totface, int totvert, void *data)
|
||||
{
|
||||
SculptSession *ss = data;
|
||||
int i;
|
||||
|
||||
/* Update face normals */
|
||||
for(i = 0; i < totface; ++i) {
|
||||
MFace *f = ss->mface + face_indices[i];
|
||||
float *fn = ss->face_normals + face_indices[i] * 3;
|
||||
|
||||
if(f->v4)
|
||||
CalcNormFloat4(ss->mvert[f->v1].co, ss->mvert[f->v2].co,
|
||||
ss->mvert[f->v3].co, ss->mvert[f->v4].co, fn);
|
||||
else
|
||||
CalcNormFloat(ss->mvert[f->v1].co, ss->mvert[f->v2].co,
|
||||
ss->mvert[f->v3].co, fn);
|
||||
}
|
||||
|
||||
/* Update vertex normals */
|
||||
for(i = 0; i < totvert; ++i) {
|
||||
const int v = vert_indices[i];
|
||||
float no[3] = {0,0,0};
|
||||
IndexNode *face;
|
||||
|
||||
for(face = ss->fmap[v].first; face; face = face->next)
|
||||
VecAddf(no, no, ss->face_normals + face->index*3);
|
||||
|
||||
Normalize(no);
|
||||
|
||||
ss->mvert[v].no[0] = no[0] * 32767;
|
||||
ss->mvert[v].no[1] = no[1] * 32767;
|
||||
ss->mvert[v].no[2] = no[2] * 32767;
|
||||
}
|
||||
}
|
||||
|
||||
static void sculpt_rebuild_tree(SculptSession *ss)
|
||||
{
|
||||
if(ss->tree)
|
||||
BLI_pbvh_free(ss->tree);
|
||||
|
||||
ss->tree = BLI_pbvh_new(sculpt_update_normals, ss);
|
||||
BLI_pbvh_build(ss->tree, ss->mface, ss->mvert, ss->totface,
|
||||
ss->totvert);
|
||||
}
|
||||
|
||||
/* Get a screen-space rectangle of the modified area */
|
||||
int sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
|
||||
Object *ob, rcti *rect)
|
||||
|
@ -1054,11 +1003,10 @@ static struct MultiresModifierData *sculpt_multires_active(Object *ob)
|
|||
static void sculpt_update_mesh_elements(bContext *C)
|
||||
{
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
DerivedMesh *dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
|
||||
SculptSession *ss = ob->sculpt;
|
||||
int oldtotvert = ss->totvert;
|
||||
|
||||
if((ss->multires = sculpt_multires_active(ob))) {
|
||||
DerivedMesh *dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
|
||||
ss->totvert = dm->getNumVerts(dm);
|
||||
ss->totface = dm->getNumFaces(dm);
|
||||
ss->mvert = dm->getVertDataArray(dm, CD_MVERT);
|
||||
|
@ -1075,17 +1023,8 @@ static void sculpt_update_mesh_elements(bContext *C)
|
|||
ss->face_normals = MEM_callocN(sizeof(float) * 3 * me->totface, "sculpt face normals");
|
||||
}
|
||||
|
||||
if(ss->tree)
|
||||
BLI_pbvh_set_source(ss->tree, ss->mvert, ss->mface);
|
||||
|
||||
if(ss->totvert != oldtotvert) {
|
||||
if(ss->fmap) MEM_freeN(ss->fmap);
|
||||
if(ss->fmap_mem) MEM_freeN(ss->fmap_mem);
|
||||
create_vert_face_map(&ss->fmap, &ss->fmap_mem, ss->mface, ss->totvert, ss->totface);
|
||||
ss->fmap_size = ss->totvert;
|
||||
|
||||
sculpt_rebuild_tree(ss);
|
||||
}
|
||||
ss->tree = dm->getPBVH(dm);
|
||||
ss->fmap = dm->getFaceMap(dm);
|
||||
}
|
||||
|
||||
static int sculpt_mode_poll(bContext *C)
|
||||
|
|
|
@ -2692,7 +2692,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm)
|
|||
drawFacesSolid() doesn't draw the transparent faces */
|
||||
if(ob->dtx & OB_DRAWTRANSP) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
dm->drawFacesSolid(dm, NULL, NULL, GPU_enable_material);
|
||||
dm->drawFacesSolid(dm, NULL, GPU_enable_material);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
GPU_disable_material();
|
||||
}
|
||||
|
@ -2802,10 +2802,10 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
|
|||
ob->sculpt->partial_redraw = 0;
|
||||
}
|
||||
|
||||
dm->drawFacesSolid(dm, ob->sculpt->tree, fpl, GPU_enable_material);
|
||||
dm->drawFacesSolid(dm, fpl, GPU_enable_material);
|
||||
}
|
||||
else
|
||||
dm->drawFacesSolid(dm, NULL, NULL, GPU_enable_material);
|
||||
dm->drawFacesSolid(dm, NULL, GPU_enable_material);
|
||||
|
||||
GPU_disable_material();
|
||||
|
||||
|
@ -6276,7 +6276,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
|
|||
glEnable(GL_LIGHTING);
|
||||
|
||||
if(dm) {
|
||||
dm->drawFacesSolid(dm, NULL, NULL, GPU_enable_material);
|
||||
dm->drawFacesSolid(dm, NULL, GPU_enable_material);
|
||||
GPU_end_object_materials();
|
||||
}
|
||||
else if(edm)
|
||||
|
|
Loading…
Reference in New Issue