Add dynamic topology support to the PBVH
* Add BLI_pbvh_build_bmesh(), similar to the other PBVH builders but specialized for BMesh. Whereas the PBVH leaf nodes for mesh and grids only store a start-index and count into the primitive indices array, the BMesh version uses GHashes to store the full set of faces and vertices in leaf nodes * Update PBVH iterator to handle BMesh * Make some of the pbvh.c functions non-static so they can be used by the new pbvh_bmesh code * The BLI_pbvh_bmesh_update_topology() function is the main reason for adding BMesh support to the PBVH. This function is used during a sculpt stroke to dynamically collapse edges that are particular short and subdivide edges that are particularly long.
This commit is contained in:
@@ -27,13 +27,18 @@
|
||||
*/
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
/* Needed for BMesh functions used in the PBVH iterator macro */
|
||||
#include "bmesh.h"
|
||||
|
||||
struct CCGElem;
|
||||
struct CCGKey;
|
||||
struct CustomData;
|
||||
struct DMFlagMat;
|
||||
struct DMGridAdjacency;
|
||||
struct ListBase;
|
||||
struct GHash;
|
||||
struct MFace;
|
||||
struct MVert;
|
||||
struct PBVH;
|
||||
@@ -63,6 +68,9 @@ void BLI_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
|
||||
struct DMGridAdjacency *gridadj, int totgrid,
|
||||
struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
|
||||
unsigned int **grid_hidden);
|
||||
void BLI_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, int smooth_shading,
|
||||
struct BMLog *log);
|
||||
|
||||
void BLI_pbvh_free(PBVH *bvh);
|
||||
|
||||
/* Hierarchical Search in the BVH, two methods:
|
||||
@@ -86,7 +94,7 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
|
||||
const float ray_start[3], const float ray_normal[3],
|
||||
int original);
|
||||
|
||||
int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
|
||||
int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
|
||||
const float ray_start[3], const float ray_normal[3],
|
||||
float *dist);
|
||||
|
||||
@@ -100,6 +108,7 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
|
||||
typedef enum {
|
||||
PBVH_FACES,
|
||||
PBVH_GRIDS,
|
||||
PBVH_BMESH
|
||||
} PBVHType;
|
||||
|
||||
PBVHType BLI_pbvh_type(const PBVH *bvh);
|
||||
@@ -110,6 +119,17 @@ unsigned int **BLI_pbvh_grid_hidden(const PBVH *bvh);
|
||||
/* multires level, only valid for type == PBVH_GRIDS */
|
||||
void BLI_pbvh_get_grid_key(const PBVH *pbvh, struct CCGKey *key);
|
||||
|
||||
/* Only valid for type == PBVH_BMESH */
|
||||
BMesh *BLI_pbvh_get_bmesh(PBVH *pbvh);
|
||||
void BLI_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size);
|
||||
|
||||
typedef enum {
|
||||
PBVH_Subdivide = 1,
|
||||
PBVH_Collapse = 2,
|
||||
} PBVHTopologyUpdateMode;
|
||||
int BLI_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
|
||||
const float center[3], float radius);
|
||||
|
||||
/* Node Access */
|
||||
|
||||
typedef enum {
|
||||
@@ -122,12 +142,15 @@ typedef enum {
|
||||
PBVH_UpdateRedraw = 32,
|
||||
|
||||
PBVH_RebuildDrawBuffers = 64,
|
||||
PBVH_FullyHidden = 128
|
||||
PBVH_FullyHidden = 128,
|
||||
|
||||
PBVH_UpdateTopology = 256,
|
||||
} PBVHNodeFlags;
|
||||
|
||||
void BLI_pbvh_node_mark_update(PBVHNode *node);
|
||||
void BLI_pbvh_node_mark_rebuild_draw(PBVHNode *node);
|
||||
void BLI_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden);
|
||||
void BLI_pbvh_node_mark_topology_update(PBVHNode *node);
|
||||
|
||||
void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node,
|
||||
int **grid_indices, int *totgrid, int *maxgrid, int *gridsize,
|
||||
@@ -147,6 +170,11 @@ int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data);
|
||||
/* test if AABB is at least partially outside the planes' volume */
|
||||
int BLI_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data);
|
||||
|
||||
struct GHash *BLI_pbvh_bmesh_node_unique_verts(PBVHNode *node);
|
||||
struct GHash *BLI_pbvh_bmesh_node_other_verts(PBVHNode *node);
|
||||
void BLI_pbvh_bmesh_node_save_orig(PBVHNode *node);
|
||||
void BLI_pbvh_bmesh_after_stroke(PBVH *bvh);
|
||||
|
||||
/* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */
|
||||
|
||||
void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]);
|
||||
@@ -169,7 +197,6 @@ float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3];
|
||||
void BLI_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3]);
|
||||
int BLI_pbvh_isDeformed(struct PBVH *pbvh);
|
||||
|
||||
|
||||
/* Vertex Iterator */
|
||||
|
||||
/* this iterator has quite a lot of code, but it's designed to:
|
||||
@@ -205,9 +232,15 @@ typedef struct PBVHVertexIter {
|
||||
int *vert_indices;
|
||||
float *vmask;
|
||||
|
||||
/* bmesh */
|
||||
struct GHashIterator bm_unique_verts;
|
||||
struct GHashIterator bm_other_verts;
|
||||
struct CustomData *bm_vdata;
|
||||
|
||||
/* result: these are all computed in the macro, but we assume
|
||||
* that compiler optimization's will skip the ones we don't use */
|
||||
struct MVert *mvert;
|
||||
struct BMVert *bm_vert;
|
||||
float *co;
|
||||
short *no;
|
||||
float *fno;
|
||||
@@ -249,7 +282,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
else if (vi.mverts) { \
|
||||
vi.mvert = &vi.mverts[vi.vert_indices[vi.gx]]; \
|
||||
if (mode == PBVH_ITER_UNIQUE && vi.mvert->flag & ME_HIDE) \
|
||||
continue; \
|
||||
@@ -258,6 +291,24 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
|
||||
if (vi.vmask) \
|
||||
vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \
|
||||
} \
|
||||
else { \
|
||||
if (!BLI_ghashIterator_isDone(&vi.bm_unique_verts)) {\
|
||||
vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \
|
||||
BLI_ghashIterator_step(&vi.bm_unique_verts); \
|
||||
} \
|
||||
else { \
|
||||
vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_other_verts); \
|
||||
BLI_ghashIterator_step(&vi.bm_other_verts); \
|
||||
} \
|
||||
if (mode == PBVH_ITER_UNIQUE && \
|
||||
BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \
|
||||
continue; \
|
||||
vi.co = vi.bm_vert->co; \
|
||||
vi.fno = vi.bm_vert->no; \
|
||||
vi.mask = CustomData_bmesh_get(vi.bm_vdata, \
|
||||
vi.bm_vert->head.data, \
|
||||
CD_PAINT_MASK); \
|
||||
}
|
||||
|
||||
#define BLI_pbvh_vertex_iter_end \
|
||||
} \
|
||||
|
@@ -124,6 +124,7 @@ set(SRC
|
||||
intern/particle.c
|
||||
intern/particle_system.c
|
||||
intern/pbvh.c
|
||||
intern/pbvh_bmesh.c
|
||||
intern/pointcache.c
|
||||
intern/property.c
|
||||
intern/report.c
|
||||
|
@@ -66,14 +66,14 @@ typedef struct PBVHIter {
|
||||
int stackspace;
|
||||
} PBVHIter;
|
||||
|
||||
static void BB_reset(BB *bb)
|
||||
void BB_reset(BB *bb)
|
||||
{
|
||||
bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX;
|
||||
bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
|
||||
}
|
||||
|
||||
/* Expand the bounding box to include a new coordinate */
|
||||
static void BB_expand(BB *bb, float co[3])
|
||||
void BB_expand(BB *bb, const float co[3])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
@@ -83,7 +83,7 @@ static void BB_expand(BB *bb, float co[3])
|
||||
}
|
||||
|
||||
/* Expand the bounding box to include another bounding box */
|
||||
static void BB_expand_with_bb(BB *bb, BB *bb2)
|
||||
void BB_expand_with_bb(BB *bb, BB *bb2)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
@@ -93,7 +93,7 @@ static void BB_expand_with_bb(BB *bb, BB *bb2)
|
||||
}
|
||||
|
||||
/* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
|
||||
static int BB_widest_axis(BB *bb)
|
||||
int BB_widest_axis(const BB *bb)
|
||||
{
|
||||
float dim[3];
|
||||
int i;
|
||||
@@ -115,7 +115,7 @@ static int BB_widest_axis(BB *bb)
|
||||
}
|
||||
}
|
||||
|
||||
static void BBC_update_centroid(BBC *bbc)
|
||||
void BBC_update_centroid(BBC *bbc)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; ++i)
|
||||
@@ -220,7 +220,7 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
|
||||
}
|
||||
}
|
||||
|
||||
static void grow_nodes(PBVH *bvh, int totnode)
|
||||
void pbvh_grow_nodes(PBVH *bvh, int totnode)
|
||||
{
|
||||
if (totnode > bvh->node_mem_count) {
|
||||
PBVHNode *prev = bvh->nodes;
|
||||
@@ -433,7 +433,7 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
|
||||
|
||||
/* Add two child nodes */
|
||||
bvh->nodes[node_index].children_offset = bvh->totnode;
|
||||
grow_nodes(bvh, bvh->totnode + 2);
|
||||
pbvh_grow_nodes(bvh, bvh->totnode + 2);
|
||||
|
||||
/* Update parent node bounding box */
|
||||
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
|
||||
@@ -601,6 +601,13 @@ void BLI_pbvh_free(PBVH *bvh)
|
||||
if (node->face_vert_indices)
|
||||
MEM_freeN(node->face_vert_indices);
|
||||
BLI_pbvh_node_layer_disp_free(node);
|
||||
|
||||
if (node->bm_faces)
|
||||
BLI_ghash_free(node->bm_faces, NULL, NULL);
|
||||
if (node->bm_unique_verts)
|
||||
BLI_ghash_free(node->bm_unique_verts, NULL, NULL);
|
||||
if (node->bm_other_verts)
|
||||
BLI_ghash_free(node->bm_other_verts, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,6 +627,11 @@ void BLI_pbvh_free(PBVH *bvh)
|
||||
if (bvh->prim_indices)
|
||||
MEM_freeN(bvh->prim_indices);
|
||||
|
||||
if (bvh->bm_vert_to_node)
|
||||
BLI_ghash_free(bvh->bm_vert_to_node, NULL, NULL);
|
||||
if (bvh->bm_face_to_node)
|
||||
BLI_ghash_free(bvh->bm_face_to_node, NULL, NULL);
|
||||
|
||||
MEM_freeN(bvh);
|
||||
}
|
||||
|
||||
@@ -900,6 +912,11 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
|
||||
float (*vnor)[3];
|
||||
int n;
|
||||
|
||||
if (bvh->type == PBVH_BMESH) {
|
||||
pbvh_bmesh_normals_update(nodes, totnode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bvh->type != PBVH_FACES)
|
||||
return;
|
||||
|
||||
@@ -993,8 +1010,7 @@ static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
|
||||
MEM_freeN(vnor);
|
||||
}
|
||||
|
||||
static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes,
|
||||
int totnode, int flag)
|
||||
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
|
||||
{
|
||||
int n;
|
||||
|
||||
@@ -1041,6 +1057,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
|
||||
node->prim_indices,
|
||||
node->totprim);
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
node->draw_buffers =
|
||||
GPU_build_bmesh_buffers(bvh->flags &
|
||||
PBVH_DYNTOPO_SMOOTH_SHADING);
|
||||
break;
|
||||
}
|
||||
|
||||
node->flag &= ~PBVH_RebuildDrawBuffers;
|
||||
@@ -1068,6 +1089,13 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
|
||||
node->face_vert_indices,
|
||||
bvh->show_diffuse_color);
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
GPU_update_bmesh_buffers(node->draw_buffers,
|
||||
bvh->bm,
|
||||
node->bm_faces,
|
||||
node->bm_unique_verts,
|
||||
node->bm_other_verts);
|
||||
break;
|
||||
}
|
||||
|
||||
node->flag &= ~PBVH_UpdateDrawBuffers;
|
||||
@@ -1222,6 +1250,12 @@ void BLI_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
|
||||
*key = bvh->gridkey;
|
||||
}
|
||||
|
||||
BMesh *BLI_pbvh_get_bmesh(PBVH *bvh)
|
||||
{
|
||||
BLI_assert(bvh->type == PBVH_BMESH);
|
||||
return bvh->bm;
|
||||
}
|
||||
|
||||
/***************************** Node Access ***********************************/
|
||||
|
||||
void BLI_pbvh_node_mark_update(PBVHNode *node)
|
||||
@@ -1264,6 +1298,11 @@ void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to
|
||||
if (totvert) *totvert = node->uniq_verts + node->face_verts;
|
||||
if (uniquevert) *uniquevert = node->uniq_verts;
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
tot = BLI_ghash_size(node->bm_unique_verts);
|
||||
if (totvert) *totvert = tot + BLI_ghash_size(node->bm_other_verts);
|
||||
if (uniquevert) *uniquevert = tot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1279,6 +1318,7 @@ void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int
|
||||
if (gridadj) *gridadj = bvh->gridadj;
|
||||
break;
|
||||
case PBVH_FACES:
|
||||
case PBVH_BMESH:
|
||||
if (grid_indices) *grid_indices = NULL;
|
||||
if (totgrid) *totgrid = 0;
|
||||
if (maxgrid) *maxgrid = 0;
|
||||
@@ -1345,11 +1385,11 @@ void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data,
|
||||
BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
|
||||
}
|
||||
|
||||
static int ray_face_intersection(const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
const float *t0, const float *t1,
|
||||
const float *t2, const float *t3,
|
||||
float *fdist)
|
||||
int ray_face_intersection(const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
const float *t0, const float *t1,
|
||||
const float *t2, const float *t3,
|
||||
float *fdist)
|
||||
{
|
||||
float dist;
|
||||
|
||||
@@ -1455,7 +1495,7 @@ static int pbvh_grids_node_raycast(PBVH *bvh, PBVHNode *node,
|
||||
return hit;
|
||||
}
|
||||
|
||||
int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
|
||||
int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use_origco,
|
||||
const float ray_start[3], const float ray_normal[3],
|
||||
float *dist)
|
||||
{
|
||||
@@ -1473,6 +1513,9 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3],
|
||||
hit |= pbvh_grids_node_raycast(bvh, node, origco,
|
||||
ray_start, ray_normal, dist);
|
||||
break;
|
||||
case PBVH_BMESH:
|
||||
hit = pbvh_bmesh_node_raycast(node, ray_start, ray_normal, dist, use_origco);
|
||||
break;
|
||||
}
|
||||
|
||||
return hit;
|
||||
@@ -1803,12 +1846,18 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
|
||||
vi->vert_indices = vert_indices;
|
||||
vi->mverts = verts;
|
||||
|
||||
if (bvh->type == PBVH_BMESH) {
|
||||
BLI_ghashIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
|
||||
BLI_ghashIterator_init(&vi->bm_other_verts, node->bm_other_verts);
|
||||
vi->bm_vdata = &bvh->bm->vdata;
|
||||
}
|
||||
|
||||
vi->gh = NULL;
|
||||
if (vi->grids && mode == PBVH_ITER_UNIQUE)
|
||||
vi->grid_hidden = bvh->grid_hidden;
|
||||
|
||||
vi->mask = NULL;
|
||||
if (!vi->grids)
|
||||
if (bvh->type == PBVH_FACES)
|
||||
vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
|
||||
}
|
||||
|
||||
|
1414
source/blender/blenkernel/intern/pbvh_bmesh.c
Normal file
1414
source/blender/blenkernel/intern/pbvh_bmesh.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,8 @@ typedef struct {
|
||||
float bmin[3], bmax[3], bcentroid[3];
|
||||
} BBC;
|
||||
|
||||
/* Note: this structure is getting large, might want to split it into
|
||||
* union'd structs */
|
||||
struct PBVHNode {
|
||||
/* Opaque handle for drawing code */
|
||||
GPU_Buffers *draw_buffers;
|
||||
@@ -86,7 +88,7 @@ struct PBVHNode {
|
||||
|
||||
/* Indicates whether this node is a leaf or not; also used for
|
||||
* marking various updates that need to be applied. */
|
||||
PBVHNodeFlags flag : 8;
|
||||
PBVHNodeFlags flag : 16;
|
||||
|
||||
/* Used for raycasting: how close bb is to the ray point. */
|
||||
float tmin;
|
||||
@@ -96,10 +98,25 @@ struct PBVHNode {
|
||||
|
||||
int proxy_count;
|
||||
PBVHProxyNode *proxies;
|
||||
|
||||
/* Dyntopo */
|
||||
GHash *bm_faces;
|
||||
GHash *bm_unique_verts;
|
||||
GHash *bm_other_verts;
|
||||
float (*bm_orco)[3];
|
||||
int (*bm_ortri)[3];
|
||||
int bm_tot_ortri;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PBVH_DYNTOPO_SMOOTH_SHADING = 1
|
||||
} PBVHFlags;
|
||||
|
||||
typedef struct PBVHBMeshLog PBVHBMeshLog;
|
||||
|
||||
struct PBVH {
|
||||
PBVHType type;
|
||||
PBVHFlags flags;
|
||||
|
||||
PBVHNode *nodes;
|
||||
int node_mem_count, totnode;
|
||||
@@ -136,6 +153,34 @@ struct PBVH {
|
||||
int deformed;
|
||||
|
||||
int show_diffuse_color;
|
||||
|
||||
/* Dynamic topology */
|
||||
BMesh *bm;
|
||||
GHash *bm_face_to_node;
|
||||
GHash *bm_vert_to_node;
|
||||
float bm_max_edge_len;
|
||||
float bm_min_edge_len;
|
||||
|
||||
struct BMLog *bm_log;
|
||||
};
|
||||
|
||||
/* pbvh.c */
|
||||
void BB_reset(BB *bb);
|
||||
void BB_expand(BB *bb, const float co[3]);
|
||||
void BB_expand_with_bb(BB *bb, BB *bb2);
|
||||
void BBC_update_centroid(BBC *bbc);
|
||||
int BB_widest_axis(const BB *bb);
|
||||
void pbvh_grow_nodes(PBVH *bvh, int totnode);
|
||||
int ray_face_intersection(const float ray_start[3], const float ray_normal[3],
|
||||
const float *t0, const float *t1, const float *t2,
|
||||
const float *t3, float *fdist);
|
||||
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
|
||||
|
||||
/* pbvh_bmesh.c */
|
||||
int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3],
|
||||
const float ray_normal[3], float *dist,
|
||||
int use_original);
|
||||
|
||||
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user