Sculpt: Improve mesh normals update performance #116209
@ -769,7 +769,7 @@ size_t blf_font_width_to_rstrlen(
|
||||
|
||||
i_tmp = i;
|
||||
g = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i_tmp, nullptr);
|
||||
for (width_new = pen_x = 0; (s != nullptr);
|
||||
for (width_new = pen_x = 0; (s != nullptr && i > 0);
|
||||
i = i_prev, s = s_prev, g = g_prev, g_prev = nullptr, width_new = pen_x)
|
||||
{
|
||||
s_prev = BLI_str_find_prev_char_utf8(s, str);
|
||||
|
@ -809,27 +809,6 @@ BLI_INLINE void *BKE_sculpt_vertex_attr_get(const PBVHVertRef vertex, const Scul
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_INLINE void *BKE_sculpt_face_attr_get(const PBVHFaceRef vertex, const SculptAttribute *attr)
|
||||
{
|
||||
if (attr->data) {
|
||||
char *p = (char *)attr->data;
|
||||
int idx = (int)vertex.i;
|
||||
|
||||
if (attr->data_for_bmesh) {
|
||||
BMElem *v = (BMElem *)vertex.i;
|
||||
idx = v->head.index;
|
||||
}
|
||||
|
||||
return p + attr->elem_size * (int)idx;
|
||||
}
|
||||
else {
|
||||
BMElem *v = (BMElem *)vertex.i;
|
||||
return BM_ELEM_CD_GET_VOID_P(v, attr->bmesh_cd_offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new color layer on object if it doesn't have one and if experimental feature set has
|
||||
* sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise.
|
||||
|
@ -65,20 +65,6 @@ struct PBVHVertRef {
|
||||
PBVH_REF_CXX_METHODS(PBVHVertRef)
|
||||
};
|
||||
|
||||
/* NOTE: edges in PBVH_GRIDS are always pulled from the base mesh. */
|
||||
struct PBVHEdgeRef {
|
||||
intptr_t i;
|
||||
|
||||
PBVH_REF_CXX_METHODS(PBVHVertRef)
|
||||
};
|
||||
|
||||
/* NOTE: faces in PBVH_GRIDS are always puled from the base mesh. */
|
||||
struct PBVHFaceRef {
|
||||
intptr_t i;
|
||||
|
||||
PBVH_REF_CXX_METHODS(PBVHVertRef)
|
||||
};
|
||||
|
||||
#define PBVH_REF_NONE -1LL
|
||||
|
||||
/* Public members of PBVH, used for inlined functions. */
|
||||
|
@ -111,18 +111,6 @@ BLI_INLINE PBVHVertRef BKE_pbvh_make_vref(intptr_t i)
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLI_INLINE PBVHEdgeRef BKE_pbvh_make_eref(intptr_t i)
|
||||
{
|
||||
PBVHEdgeRef ret = {i};
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLI_INLINE PBVHFaceRef BKE_pbvh_make_fref(intptr_t i)
|
||||
{
|
||||
PBVHFaceRef ret = {i};
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLI_INLINE int BKE_pbvh_vertex_to_index(PBVH *pbvh, PBVHVertRef v)
|
||||
{
|
||||
return (BKE_pbvh_type(pbvh) == PBVH_BMESH && v.i != PBVH_REF_NONE ?
|
||||
@ -143,46 +131,6 @@ BLI_INLINE PBVHVertRef BKE_pbvh_index_to_vertex(PBVH *pbvh, int index)
|
||||
return BKE_pbvh_make_vref(PBVH_REF_NONE);
|
||||
}
|
||||
|
||||
BLI_INLINE int BKE_pbvh_edge_to_index(PBVH *pbvh, PBVHEdgeRef e)
|
||||
{
|
||||
return (BKE_pbvh_type(pbvh) == PBVH_BMESH && e.i != PBVH_REF_NONE ?
|
||||
BM_elem_index_get((BMEdge *)(e.i)) :
|
||||
(e.i));
|
||||
}
|
||||
|
||||
BLI_INLINE PBVHEdgeRef BKE_pbvh_index_to_edge(PBVH *pbvh, int index)
|
||||
{
|
||||
switch (BKE_pbvh_type(pbvh)) {
|
||||
case PBVH_FACES:
|
||||
case PBVH_GRIDS:
|
||||
return BKE_pbvh_make_eref(index);
|
||||
case PBVH_BMESH:
|
||||
return BKE_pbvh_make_eref((intptr_t)BKE_pbvh_get_bmesh(pbvh)->etable[index]);
|
||||
}
|
||||
|
||||
return BKE_pbvh_make_eref(PBVH_REF_NONE);
|
||||
}
|
||||
|
||||
BLI_INLINE int BKE_pbvh_face_to_index(PBVH *pbvh, PBVHFaceRef f)
|
||||
{
|
||||
return (BKE_pbvh_type(pbvh) == PBVH_BMESH && f.i != PBVH_REF_NONE ?
|
||||
BM_elem_index_get((BMFace *)(f.i)) :
|
||||
(f.i));
|
||||
}
|
||||
|
||||
BLI_INLINE PBVHFaceRef BKE_pbvh_index_to_face(PBVH *pbvh, int index)
|
||||
{
|
||||
switch (BKE_pbvh_type(pbvh)) {
|
||||
case PBVH_FACES:
|
||||
case PBVH_GRIDS:
|
||||
return BKE_pbvh_make_fref(index);
|
||||
case PBVH_BMESH:
|
||||
return BKE_pbvh_make_fref((intptr_t)BKE_pbvh_get_bmesh(pbvh)->ftable[index]);
|
||||
}
|
||||
|
||||
return BKE_pbvh_make_fref(PBVH_REF_NONE);
|
||||
}
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
/**
|
||||
@ -193,24 +141,23 @@ using BKE_pbvh_HitCallback = void (*)(PBVHNode *node, void *data);
|
||||
using BKE_pbvh_HitOccludedCallback = void (*)(PBVHNode *node, void *data, float *tmin);
|
||||
using BKE_pbvh_SearchNearestCallback = void (*)(PBVHNode *node, void *data, float *tmin);
|
||||
|
||||
/* Building */
|
||||
|
||||
PBVH *BKE_pbvh_new(PBVHType type);
|
||||
namespace blender::bke::pbvh {
|
||||
|
||||
/**
|
||||
* Do a full rebuild with on Mesh data structure.
|
||||
*/
|
||||
void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh);
|
||||
void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh);
|
||||
PBVH *build_mesh(Mesh *mesh);
|
||||
void update_mesh_pointers(PBVH *pbvh, Mesh *mesh);
|
||||
/**
|
||||
* Do a full rebuild with on Grids data structure.
|
||||
*/
|
||||
void BKE_pbvh_build_grids(PBVH *pbvh, const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg);
|
||||
PBVH *build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg);
|
||||
/**
|
||||
* Build a PBVH from a BMesh.
|
||||
*/
|
||||
void BKE_pbvh_build_bmesh(
|
||||
PBVH *pbvh, BMesh *bm, BMLog *log, int cd_vert_node_offset, int cd_face_node_offset);
|
||||
PBVH *build_bmesh(BMesh *bm, BMLog *log, int cd_vert_node_offset, int cd_face_node_offset);
|
||||
|
||||
} // namespace blender::bke::pbvh
|
||||
|
||||
void BKE_pbvh_update_bmesh_offsets(PBVH *pbvh, int cd_vert_node_offset, int cd_face_node_offset);
|
||||
|
||||
@ -314,14 +261,17 @@ blender::Bounds<blender::float3> BKE_pbvh_bounding_box(const PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh);
|
||||
|
||||
namespace blender::bke::pbvh {
|
||||
|
||||
/**
|
||||
* Returns the number of visible quads in the nodes' grids.
|
||||
*/
|
||||
int BKE_pbvh_count_grid_quads(const blender::BitGroupVector<> &grid_visibility,
|
||||
const int *grid_indices,
|
||||
int totgrid,
|
||||
int gridsize,
|
||||
int display_gridsize);
|
||||
int count_grid_quads(const BitGroupVector<> &grid_visibility,
|
||||
Span<int> grid_indices,
|
||||
int gridsize,
|
||||
int display_gridsize);
|
||||
|
||||
} // namespace blender::bke::pbvh
|
||||
|
||||
/**
|
||||
* Multi-res level, only valid for type == #PBVH_GRIDS.
|
||||
|
@ -2106,26 +2106,22 @@ void BKE_sculpt_sync_face_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)
|
||||
});
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
|
||||
{
|
||||
PBVH *pbvh = ob->sculpt->pbvh = BKE_pbvh_new(PBVH_BMESH);
|
||||
|
||||
sculptsession_bmesh_add_layers(ob);
|
||||
|
||||
BKE_pbvh_build_bmesh(pbvh,
|
||||
ob->sculpt->bm,
|
||||
ob->sculpt->bm_log,
|
||||
ob->sculpt->attrs.dyntopo_node_id_vertex->bmesh_cd_offset,
|
||||
ob->sculpt->attrs.dyntopo_node_id_face->bmesh_cd_offset);
|
||||
return pbvh;
|
||||
return pbvh::build_bmesh(ob->sculpt->bm,
|
||||
ob->sculpt->bm_log,
|
||||
ob->sculpt->attrs.dyntopo_node_id_vertex->bmesh_cd_offset,
|
||||
ob->sculpt->attrs.dyntopo_node_id_face->bmesh_cd_offset);
|
||||
}
|
||||
|
||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
|
||||
{
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
PBVH *pbvh = BKE_pbvh_new(PBVH_FACES);
|
||||
|
||||
BKE_pbvh_build_mesh(pbvh, mesh);
|
||||
PBVH *pbvh = pbvh::build_mesh(mesh);
|
||||
|
||||
const bool is_deformed = check_sculpt_object_deformed(ob, true);
|
||||
if (is_deformed && me_eval_deform != nullptr) {
|
||||
@ -2138,17 +2134,17 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
|
||||
static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
const CCGKey key = BKE_subdiv_ccg_key_top_level(*subdiv_ccg);
|
||||
PBVH *pbvh = BKE_pbvh_new(PBVH_GRIDS);
|
||||
|
||||
Mesh *base_mesh = BKE_mesh_from_object(ob);
|
||||
BKE_sculpt_sync_face_visibility_to_grids(base_mesh, subdiv_ccg);
|
||||
|
||||
BKE_pbvh_build_grids(pbvh, &key, base_mesh, subdiv_ccg);
|
||||
return pbvh;
|
||||
return pbvh::build_grids(&key, base_mesh, subdiv_ccg);
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
if (ob->sculpt == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -2160,7 +2156,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||
const PBVHType pbvh_type = BKE_pbvh_type(pbvh);
|
||||
switch (pbvh_type) {
|
||||
case PBVH_FACES: {
|
||||
BKE_pbvh_update_mesh_pointers(pbvh, BKE_object_get_original_mesh(ob));
|
||||
pbvh::update_mesh_pointers(pbvh, BKE_object_get_original_mesh(ob));
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
@ -2264,16 +2260,13 @@ void BKE_paint_face_set_overlay_color_get(const int face_set, const int seed, uc
|
||||
|
||||
int BKE_sculptsession_vertex_count(const SculptSession *ss)
|
||||
{
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
return ss->totvert;
|
||||
case PBVH_BMESH:
|
||||
return BM_mesh_elem_count(ss->bm, BM_VERT);
|
||||
case PBVH_GRIDS:
|
||||
return BKE_pbvh_get_grid_num_verts(ss->pbvh);
|
||||
if (ss->bm) {
|
||||
return ss->bm->totvert;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (ss->subdiv_ccg) {
|
||||
return ss->subdiv_ccg->grids.size() * BKE_subdiv_ccg_key_top_level(*ss->subdiv_ccg).grid_area;
|
||||
}
|
||||
return ss->totvert;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2390,79 +2383,67 @@ static bool sculpt_attribute_create(SculptSession *ss,
|
||||
|
||||
out->simple_array = false;
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH: {
|
||||
CustomData *cdata = nullptr;
|
||||
out->data_for_bmesh = true;
|
||||
if (BMesh *bm = ss->bm) {
|
||||
CustomData *cdata = nullptr;
|
||||
out->data_for_bmesh = true;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &ss->bm->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &ss->bm->pdata;
|
||||
break;
|
||||
default:
|
||||
out->used = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_assert(CustomData_get_named_layer_index(cdata, proptype, name) == -1);
|
||||
|
||||
BM_data_layer_add_named(ss->bm, cdata, proptype, name);
|
||||
int index = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
out->data = nullptr;
|
||||
out->layer = cdata->layers + index;
|
||||
out->bmesh_cd_offset = out->layer->offset;
|
||||
out->elem_size = CustomData_sizeof(proptype);
|
||||
break;
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &bm->vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &bm->pdata;
|
||||
break;
|
||||
default:
|
||||
out->used = false;
|
||||
return false;
|
||||
}
|
||||
case PBVH_FACES: {
|
||||
CustomData *cdata = nullptr;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &mesh->vert_data;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &mesh->face_data;
|
||||
break;
|
||||
default:
|
||||
out->used = false;
|
||||
return false;
|
||||
}
|
||||
BLI_assert(CustomData_get_named_layer_index(cdata, proptype, name) == -1);
|
||||
|
||||
BLI_assert(CustomData_get_named_layer_index(cdata, proptype, name) == -1);
|
||||
BM_data_layer_add_named(bm, cdata, proptype, name);
|
||||
int index = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_SET_DEFAULT, totelem, name);
|
||||
int index = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
out->layer = cdata->layers + index;
|
||||
out->data = out->layer->data;
|
||||
out->data_for_bmesh = false;
|
||||
out->bmesh_cd_offset = -1;
|
||||
out->elem_size = CustomData_get_elem_size(out->layer);
|
||||
|
||||
break;
|
||||
if (!permanent) {
|
||||
cdata->layers[index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
/* GRIDS should have been handled as simple arrays. */
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
|
||||
out->data = nullptr;
|
||||
out->layer = cdata->layers + index;
|
||||
out->bmesh_cd_offset = out->layer->offset;
|
||||
out->elem_size = CustomData_sizeof(proptype);
|
||||
}
|
||||
else {
|
||||
CustomData *cdata = nullptr;
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
cdata = &mesh->vert_data;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
cdata = &mesh->face_data;
|
||||
break;
|
||||
default:
|
||||
out->used = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_assert(CustomData_get_named_layer_index(cdata, proptype, name) == -1);
|
||||
|
||||
CustomData_add_layer_named(cdata, proptype, CD_SET_DEFAULT, totelem, name);
|
||||
int index = CustomData_get_named_layer_index(cdata, proptype, name);
|
||||
|
||||
if (!permanent) {
|
||||
cdata->layers[index].flag |= CD_FLAG_TEMPORARY | CD_FLAG_NOCOPY;
|
||||
}
|
||||
|
||||
out->layer = cdata->layers + index;
|
||||
out->data = out->layer->data;
|
||||
out->data_for_bmesh = false;
|
||||
out->bmesh_cd_offset = -1;
|
||||
out->elem_size = CustomData_get_elem_size(out->layer);
|
||||
}
|
||||
/* GRIDS should have been handled as simple arrays. */
|
||||
|
||||
out->used = true;
|
||||
out->elem_num = totelem;
|
||||
|
@ -146,8 +146,6 @@ static void update_node_vb(PBVH *pbvh, PBVHNode *node)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke::pbvh
|
||||
|
||||
static bool face_materials_match(const Span<int> material_indices,
|
||||
const Span<bool> sharp_faces,
|
||||
const int a,
|
||||
@ -168,7 +166,7 @@ static bool face_materials_match(const Span<int> material_indices,
|
||||
|
||||
/* Adapted from BLI_kdopbvh.c */
|
||||
/* Returns the index of the first element on the right of the partition */
|
||||
static int partition_prim_indices(blender::MutableSpan<int> prim_indices,
|
||||
static int partition_prim_indices(MutableSpan<int> prim_indices,
|
||||
int *prim_scratch,
|
||||
int lo,
|
||||
int hi,
|
||||
@ -177,7 +175,6 @@ static int partition_prim_indices(blender::MutableSpan<int> prim_indices,
|
||||
const Span<Bounds<float3>> prim_bounds,
|
||||
const Span<int> prim_to_face_map)
|
||||
{
|
||||
using namespace blender;
|
||||
for (int i = lo; i < hi; i++) {
|
||||
prim_scratch[i - lo] = prim_indices[i];
|
||||
}
|
||||
@ -231,14 +228,9 @@ static int partition_indices_material_faces(MutableSpan<int> indices,
|
||||
}
|
||||
}
|
||||
|
||||
void pbvh_grow_nodes(PBVH *pbvh, int totnode)
|
||||
{
|
||||
pbvh->nodes.resize(totnode);
|
||||
}
|
||||
|
||||
/* Add a vertex to the map, with a positive value for unique vertices and
|
||||
* a negative value for additional vertices */
|
||||
static int map_insert_vert(blender::Map<int, int> &map,
|
||||
static int map_insert_vert(Map<int, int> &map,
|
||||
MutableSpan<bool> vert_bitmap,
|
||||
int *face_verts,
|
||||
int *uniq_verts,
|
||||
@ -271,7 +263,7 @@ static void build_mesh_leaf_node(const Span<int> corner_verts,
|
||||
const Span<int> prim_indices = node->prim_indices;
|
||||
|
||||
/* reserve size is rough guess */
|
||||
blender::Map<int, int> map;
|
||||
Map<int, int> map;
|
||||
map.reserve(prim_indices.size());
|
||||
|
||||
node->face_vert_indices.reinitialize(prim_indices.size());
|
||||
@ -287,7 +279,7 @@ static void build_mesh_leaf_node(const Span<int> corner_verts,
|
||||
node->vert_indices.reinitialize(node->uniq_verts + node->face_verts);
|
||||
|
||||
/* Build the vertex list, unique verts first */
|
||||
for (const blender::MapItem<int, int> item : map.items()) {
|
||||
for (const MapItem<int, int> item : map.items()) {
|
||||
int value = item.value;
|
||||
if (value < 0) {
|
||||
value = -value + node->uniq_verts - 1;
|
||||
@ -319,7 +311,6 @@ static void update_vb(const Span<int> prim_indices,
|
||||
int offset,
|
||||
int count)
|
||||
{
|
||||
using namespace blender;
|
||||
node->vb = prim_bounds[prim_indices[offset]];
|
||||
for (const int i : IndexRange(offset, count).drop_front(1)) {
|
||||
node->vb = bounds::merge(node->vb, prim_bounds[prim_indices[i]]);
|
||||
@ -327,15 +318,14 @@ static void update_vb(const Span<int> prim_indices,
|
||||
node->orig_vb = node->vb;
|
||||
}
|
||||
|
||||
int BKE_pbvh_count_grid_quads(const BitGroupVector<> &grid_hidden,
|
||||
const int *grid_indices,
|
||||
int totgrid,
|
||||
int gridsize,
|
||||
int display_gridsize)
|
||||
int count_grid_quads(const BitGroupVector<> &grid_hidden,
|
||||
const Span<int> grid_indices,
|
||||
int gridsize,
|
||||
int display_gridsize)
|
||||
{
|
||||
const int gridarea = (gridsize - 1) * (gridsize - 1);
|
||||
if (grid_hidden.is_empty()) {
|
||||
return gridarea * totgrid;
|
||||
return gridarea * grid_indices.size();
|
||||
}
|
||||
|
||||
/* grid hidden layer is present, so have to check each grid for
|
||||
@ -347,8 +337,8 @@ int BKE_pbvh_count_grid_quads(const BitGroupVector<> &grid_hidden,
|
||||
int skip = depth2 < depth1 ? 1 << (depth1 - depth2 - 1) : 1;
|
||||
|
||||
int totquad = 0;
|
||||
for (int i = 0; i < totgrid; i++) {
|
||||
const blender::BoundedBitSpan gh = grid_hidden[grid_indices[i]];
|
||||
for (const int grid : grid_indices) {
|
||||
const blender::BoundedBitSpan gh = grid_hidden[grid];
|
||||
/* grid hidden are present, have to check each element */
|
||||
for (int y = 0; y < gridsize - skip; y += skip) {
|
||||
for (int x = 0; x < gridsize - skip; x += skip) {
|
||||
@ -364,11 +354,10 @@ int BKE_pbvh_count_grid_quads(const BitGroupVector<> &grid_hidden,
|
||||
|
||||
static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
int totquads = BKE_pbvh_count_grid_quads(pbvh->subdiv_ccg->grid_hidden,
|
||||
node->prim_indices.data(),
|
||||
node->prim_indices.size(),
|
||||
pbvh->gridkey.grid_size,
|
||||
pbvh->gridkey.grid_size);
|
||||
int totquads = count_grid_quads(pbvh->subdiv_ccg->grid_hidden,
|
||||
node->prim_indices,
|
||||
pbvh->gridkey.grid_size,
|
||||
pbvh->gridkey.grid_size);
|
||||
BKE_pbvh_node_fully_hidden_set(node, (totquads == 0));
|
||||
BKE_pbvh_node_mark_rebuild_draw(node);
|
||||
}
|
||||
@ -499,7 +488,6 @@ static void build_sub(PBVH *pbvh,
|
||||
int *prim_scratch,
|
||||
int depth)
|
||||
{
|
||||
using namespace blender;
|
||||
const Span<int> prim_to_face_map = pbvh->header.type == PBVH_FACES ?
|
||||
looptri_faces :
|
||||
pbvh->subdiv_ccg->grid_to_face_map;
|
||||
@ -536,7 +524,7 @@ static void build_sub(PBVH *pbvh,
|
||||
|
||||
/* Add two child nodes */
|
||||
pbvh->nodes[node_index].children_offset = pbvh->nodes.size();
|
||||
pbvh_grow_nodes(pbvh, pbvh->nodes.size() + 2);
|
||||
pbvh->nodes.resize(pbvh->nodes.size() + 2);
|
||||
|
||||
/* Update parent node bounding box */
|
||||
update_vb(pbvh->prim_indices, &pbvh->nodes[node_index], prim_bounds, offset, count);
|
||||
@ -629,7 +617,7 @@ static void pbvh_build(PBVH *pbvh,
|
||||
pbvh->nodes.clear_and_shrink();
|
||||
|
||||
pbvh->prim_indices.reinitialize(totprim);
|
||||
blender::array_utils::fill_index_range<int>(pbvh->prim_indices);
|
||||
array_utils::fill_index_range<int>(pbvh->prim_indices);
|
||||
}
|
||||
|
||||
pbvh->nodes.resize(1);
|
||||
@ -718,7 +706,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh, const Span<int> looptri_faces)
|
||||
}
|
||||
#endif
|
||||
|
||||
void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
||||
void update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
||||
{
|
||||
BLI_assert(pbvh->header.type == PBVH_FACES);
|
||||
pbvh->faces = mesh->faces();
|
||||
@ -733,24 +721,24 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
||||
PBVH *build_mesh(Mesh *mesh)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
std::unique_ptr<PBVH> pbvh = std::make_unique<PBVH>();
|
||||
pbvh->header.type = PBVH_FACES;
|
||||
|
||||
const int totvert = mesh->totvert;
|
||||
const int looptris_num = poly_to_tri_count(mesh->faces_num, mesh->totloop);
|
||||
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
|
||||
const blender::OffsetIndices<int> faces = mesh->faces();
|
||||
const OffsetIndices<int> faces = mesh->faces();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
|
||||
pbvh->looptris.reinitialize(looptris_num);
|
||||
blender::bke::mesh::looptris_calc(vert_positions, faces, corner_verts, pbvh->looptris);
|
||||
mesh::looptris_calc(vert_positions, faces, corner_verts, pbvh->looptris);
|
||||
const Span<MLoopTri> looptris = pbvh->looptris;
|
||||
|
||||
pbvh->mesh = mesh;
|
||||
pbvh->header.type = PBVH_FACES;
|
||||
|
||||
BKE_pbvh_update_mesh_pointers(pbvh, mesh);
|
||||
update_mesh_pointers(pbvh.get(), mesh);
|
||||
const Span<int> looptri_faces = pbvh->looptri_faces;
|
||||
|
||||
Array<bool> vert_bitmap(totvert, false);
|
||||
@ -793,7 +781,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
||||
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", ATTR_DOMAIN_FACE);
|
||||
const VArraySpan material_index = *attributes.lookup<int>("material_index", ATTR_DOMAIN_FACE);
|
||||
const VArraySpan sharp_face = *attributes.lookup<bool>("sharp_face", ATTR_DOMAIN_FACE);
|
||||
pbvh_build(pbvh,
|
||||
pbvh_build(pbvh.get(),
|
||||
corner_verts,
|
||||
looptris,
|
||||
looptri_faces,
|
||||
@ -810,37 +798,38 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
||||
#endif
|
||||
}
|
||||
|
||||
BKE_pbvh_update_active_vcol(pbvh, mesh);
|
||||
BKE_pbvh_update_active_vcol(pbvh.get(), mesh);
|
||||
|
||||
#ifdef VALIDATE_UNIQUE_NODE_FACES
|
||||
pbvh_validate_node_prims(pbvh);
|
||||
#endif
|
||||
|
||||
return pbvh.release();
|
||||
}
|
||||
|
||||
void BKE_pbvh_build_grids(PBVH *pbvh, const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg)
|
||||
PBVH *build_grids(const CCGKey *key, Mesh *mesh, SubdivCCG *subdiv_ccg)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
const int gridsize = key->grid_size;
|
||||
const Span<CCGElem *> grids = subdiv_ccg->grids;
|
||||
|
||||
std::unique_ptr<PBVH> pbvh = std::make_unique<PBVH>();
|
||||
pbvh->header.type = PBVH_GRIDS;
|
||||
|
||||
pbvh->gridkey = *key;
|
||||
pbvh->subdiv_ccg = subdiv_ccg;
|
||||
pbvh->faces_num = mesh->faces_num;
|
||||
|
||||
/* Find maximum number of grids per face. */
|
||||
int max_grids = 1;
|
||||
const blender::OffsetIndices faces = mesh->faces();
|
||||
const OffsetIndices faces = mesh->faces();
|
||||
for (const int i : faces.index_range()) {
|
||||
max_grids = max_ii(max_grids, faces[i].size());
|
||||
}
|
||||
|
||||
const Span<CCGElem *> grids = subdiv_ccg->grids;
|
||||
|
||||
/* Ensure leaf limit is at least 4 so there's room
|
||||
* to split at original face boundaries.
|
||||
* Fixes #102209.
|
||||
*/
|
||||
pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), max_grids);
|
||||
pbvh->leaf_limit = max_ii(LEAF_LIMIT / (key->grid_area), max_grids);
|
||||
|
||||
/* We also need the base mesh for PBVH draw. */
|
||||
pbvh->mesh = mesh;
|
||||
@ -871,8 +860,17 @@ void BKE_pbvh_build_grids(PBVH *pbvh, const CCGKey *key, Mesh *mesh, SubdivCCG *
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
const VArraySpan material_index = *attributes.lookup<int>("material_index", ATTR_DOMAIN_FACE);
|
||||
const VArraySpan sharp_face = *attributes.lookup<bool>("sharp_face", ATTR_DOMAIN_FACE);
|
||||
pbvh_build(
|
||||
pbvh, {}, {}, {}, {}, material_index, sharp_face, {}, &cb, prim_bounds, grids.size());
|
||||
pbvh_build(pbvh.get(),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
material_index,
|
||||
sharp_face,
|
||||
{},
|
||||
&cb,
|
||||
prim_bounds,
|
||||
grids.size());
|
||||
|
||||
#ifdef TEST_PBVH_FACE_SPLIT
|
||||
test_face_boundaries(pbvh);
|
||||
@ -882,20 +880,11 @@ void BKE_pbvh_build_grids(PBVH *pbvh, const CCGKey *key, Mesh *mesh, SubdivCCG *
|
||||
#ifdef VALIDATE_UNIQUE_NODE_FACES
|
||||
pbvh_validate_node_prims(pbvh);
|
||||
#endif
|
||||
|
||||
return pbvh.release();
|
||||
}
|
||||
|
||||
PBVH *BKE_pbvh_new(PBVHType type)
|
||||
{
|
||||
PBVH *pbvh = MEM_new<PBVH>(__func__);
|
||||
pbvh->draw_cache_invalid = true;
|
||||
pbvh->header.type = type;
|
||||
|
||||
/* Initialize this to true, instead of waiting for a draw engine
|
||||
* to set it. Prevents a crash in draw manager instancing code.
|
||||
*/
|
||||
pbvh->is_drawing = true;
|
||||
return pbvh;
|
||||
}
|
||||
} // namespace blender::bke::pbvh
|
||||
|
||||
void BKE_pbvh_free(PBVH *pbvh)
|
||||
{
|
||||
@ -913,7 +902,7 @@ void BKE_pbvh_free(PBVH *pbvh)
|
||||
|
||||
pbvh_pixels_free(pbvh);
|
||||
|
||||
MEM_delete(pbvh);
|
||||
delete pbvh;
|
||||
}
|
||||
|
||||
static void pbvh_iter_begin(PBVHIter *iter, PBVH *pbvh, blender::FunctionRef<bool(PBVHNode &)> scb)
|
||||
|
@ -291,7 +291,7 @@ static void pbvh_bmesh_node_split(PBVH *pbvh,
|
||||
/* Add two new child nodes. */
|
||||
const int children = pbvh->nodes.size();
|
||||
n->children_offset = children;
|
||||
pbvh_grow_nodes(pbvh, pbvh->nodes.size() + 2);
|
||||
pbvh->nodes.resize(pbvh->nodes.size() + 2);
|
||||
|
||||
/* Array reallocated, update current node pointer. */
|
||||
n = &pbvh->nodes[node_index];
|
||||
@ -2078,7 +2078,7 @@ static void pbvh_bmesh_create_nodes_fast_recursive(PBVH *pbvh,
|
||||
int children_offset = pbvh->nodes.size();
|
||||
|
||||
n->children_offset = children_offset;
|
||||
pbvh_grow_nodes(pbvh, pbvh->nodes.size() + 2);
|
||||
pbvh->nodes.resize(pbvh->nodes.size() + 2);
|
||||
pbvh_bmesh_create_nodes_fast_recursive(
|
||||
pbvh, nodeinfo, face_bounds, node->child1, children_offset);
|
||||
pbvh_bmesh_create_nodes_fast_recursive(
|
||||
@ -2158,16 +2158,19 @@ void BKE_pbvh_update_bmesh_offsets(PBVH *pbvh, int cd_vert_node_offset, int cd_f
|
||||
pbvh->cd_face_node_offset = cd_face_node_offset;
|
||||
}
|
||||
|
||||
void BKE_pbvh_build_bmesh(PBVH *pbvh,
|
||||
BMesh *bm,
|
||||
BMLog *log,
|
||||
const int cd_vert_node_offset,
|
||||
const int cd_face_node_offset)
|
||||
namespace blender::bke::pbvh {
|
||||
|
||||
PBVH *build_bmesh(BMesh *bm,
|
||||
BMLog *log,
|
||||
const int cd_vert_node_offset,
|
||||
const int cd_face_node_offset)
|
||||
{
|
||||
using namespace blender;
|
||||
std::unique_ptr<PBVH> pbvh = std::make_unique<PBVH>();
|
||||
pbvh->header.type = PBVH_BMESH;
|
||||
|
||||
pbvh->header.bm = bm;
|
||||
|
||||
BKE_pbvh_bmesh_detail_size_set(pbvh, 0.75);
|
||||
BKE_pbvh_bmesh_detail_size_set(pbvh.get(), 0.75);
|
||||
|
||||
pbvh->header.type = PBVH_BMESH;
|
||||
pbvh->bm_log = log;
|
||||
@ -2175,15 +2178,15 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
|
||||
/* TODO: choose leaf limit better. */
|
||||
pbvh->leaf_limit = 400;
|
||||
|
||||
BKE_pbvh_update_bmesh_offsets(pbvh, cd_vert_node_offset, cd_face_node_offset);
|
||||
BKE_pbvh_update_bmesh_offsets(pbvh.get(), cd_vert_node_offset, cd_face_node_offset);
|
||||
|
||||
if (bm->totface == 0) {
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
/* bounding box array of all faces, no need to recalculate every time. */
|
||||
blender::Array<Bounds<float3>> face_bounds(bm->totface);
|
||||
blender::Array<BMFace *> nodeinfo(bm->totface);
|
||||
Array<Bounds<float3>> face_bounds(bm->totface);
|
||||
Array<BMFace *> nodeinfo(bm->totface);
|
||||
MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast PBVH node storage");
|
||||
|
||||
BMIter iter;
|
||||
@ -2216,7 +2219,7 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
|
||||
rootnode.totface = bm->totface;
|
||||
|
||||
/* Start recursion, assign faces to nodes accordingly. */
|
||||
pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, face_bounds, &rootnode, arena);
|
||||
pbvh_bmesh_node_limit_ensure_fast(pbvh.get(), nodeinfo, face_bounds, &rootnode, arena);
|
||||
|
||||
/* We now have all faces assigned to a node,
|
||||
* next we need to assign those to the gsets of the nodes. */
|
||||
@ -2225,11 +2228,14 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
|
||||
pbvh->nodes.append({});
|
||||
|
||||
/* Take root node and visit and populate children recursively. */
|
||||
pbvh_bmesh_create_nodes_fast_recursive(pbvh, nodeinfo, face_bounds, &rootnode, 0);
|
||||
pbvh_bmesh_create_nodes_fast_recursive(pbvh.get(), nodeinfo, face_bounds, &rootnode, 0);
|
||||
|
||||
BLI_memarena_free(arena);
|
||||
return pbvh.release();
|
||||
}
|
||||
|
||||
} // namespace blender::bke::pbvh
|
||||
|
||||
bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
||||
PBVHTopologyUpdateMode mode,
|
||||
const float center[3],
|
||||
|
@ -193,10 +193,13 @@ struct PBVH {
|
||||
CustomDataLayer *color_layer;
|
||||
eAttrDomain color_domain;
|
||||
|
||||
bool is_drawing;
|
||||
/* Initialize this to true, instead of waiting for a draw engine
|
||||
* to set it. Prevents a crash in draw manager instancing code.
|
||||
* TODO: This is fragile, another solution should be found. */
|
||||
bool is_drawing = true;
|
||||
|
||||
/* Used by DynTopo to invalidate the draw cache. */
|
||||
bool draw_cache_invalid;
|
||||
bool draw_cache_invalid = true;
|
||||
|
||||
PBVHGPUFormat *vbo_id;
|
||||
|
||||
@ -205,7 +208,6 @@ struct PBVH {
|
||||
|
||||
/* pbvh.cc */
|
||||
|
||||
void pbvh_grow_nodes(PBVH *bvh, int totnode);
|
||||
bool ray_face_intersection_quad(const float ray_start[3],
|
||||
IsectRayPrecalc *isect_precalc,
|
||||
const float t0[3],
|
||||
|
@ -285,7 +285,7 @@ static void split_flush_final_nodes(SplitQueueData *tdata)
|
||||
if (!newsplit->parent->children_offset) {
|
||||
newsplit->parent->children_offset = pbvh->nodes.size();
|
||||
|
||||
pbvh_grow_nodes(pbvh, pbvh->nodes.size() + 2);
|
||||
pbvh->nodes.resize(pbvh->nodes.size() + 2);
|
||||
newsplit->source_index = newsplit->parent->children_offset;
|
||||
}
|
||||
else {
|
||||
|
@ -351,11 +351,10 @@ struct PBVHBatches {
|
||||
break;
|
||||
}
|
||||
case PBVH_GRIDS: {
|
||||
count = BKE_pbvh_count_grid_quads(args.subdiv_ccg->grid_hidden,
|
||||
args.grid_indices.data(),
|
||||
args.grid_indices.size(),
|
||||
args.ccg_key.grid_size,
|
||||
args.ccg_key.grid_size);
|
||||
count = bke::pbvh::count_grid_quads(args.subdiv_ccg->grid_hidden,
|
||||
args.grid_indices,
|
||||
args.ccg_key.grid_size,
|
||||
args.ccg_key.grid_size);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1163,8 +1162,8 @@ struct PBVHBatches {
|
||||
|
||||
const CCGKey *key = &args.ccg_key;
|
||||
|
||||
uint visible_quad_len = BKE_pbvh_count_grid_quads(
|
||||
grid_hidden, args.grid_indices.data(), totgrid, key->grid_size, display_gridsize);
|
||||
uint visible_quad_len = bke::pbvh::count_grid_quads(
|
||||
grid_hidden, args.grid_indices, key->grid_size, display_gridsize);
|
||||
|
||||
GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX);
|
||||
GPU_indexbuf_init(&elb_lines,
|
||||
|
@ -1886,4 +1886,3 @@ int SCULPT_vertex_island_get(const SculptSession *ss, PBVHVertRef vertex);
|
||||
/* Make SCULPT_ alias to a few blenkernel sculpt methods. */
|
||||
|
||||
#define SCULPT_vertex_attr_get BKE_sculpt_vertex_attr_get
|
||||
#define SCULPT_face_attr_get BKE_sculpt_face_attr_get
|
||||
|
@ -159,7 +159,6 @@ struct SculptUndoStep {
|
||||
};
|
||||
|
||||
static UndoSculpt *get_nodes();
|
||||
static bool sculpt_attribute_ref_equals(SculptAttrRef *a, SculptAttrRef *b);
|
||||
static void sculpt_save_active_attribute(Object *ob, SculptAttrRef *attr);
|
||||
static UndoSculpt *sculpt_undosys_step_get_nodes(UndoStep *us_p);
|
||||
|
||||
@ -1597,11 +1596,6 @@ Node *push_node(Object *ob, PBVHNode *node, Type type)
|
||||
return unode;
|
||||
}
|
||||
|
||||
static bool sculpt_attribute_ref_equals(SculptAttrRef *a, SculptAttrRef *b)
|
||||
{
|
||||
return a->domain == b->domain && a->type == b->type && STREQ(a->name, b->name);
|
||||
}
|
||||
|
||||
static void sculpt_save_active_attribute(Object *ob, SculptAttrRef *attr)
|
||||
{
|
||||
Mesh *mesh = BKE_object_get_original_mesh(ob);
|
||||
|
Loading…
Reference in New Issue
Block a user