PBVH: update mesh data pointers stored in pbvh #106271
|
@ -283,28 +283,11 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float
|
||||||
|
|
||||||
PBVH *BKE_pbvh_new(PBVHType type);
|
PBVH *BKE_pbvh_new(PBVHType type);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do a full rebuild with on Mesh data structure.
|
* Do a full rebuild with on Mesh data structure.
|
||||||
*
|
|
||||||
* \note Unlike mpoly/corner_verts/verts, looptri is *totally owned* by PBVH
|
|
||||||
* (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
|
|
||||||
*/
|
*/
|
||||||
void BKE_pbvh_build_mesh(PBVH *pbvh,
|
void BKE_pbvh_build_mesh(PBVH *pbvh, struct Mesh *mesh);
|
||||||
struct Mesh *mesh,
|
void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, struct Mesh *mesh);
|
||||||
blender::OffsetIndices<int> polys,
|
|
||||||
const int *corner_verts,
|
|
||||||
float (*vert_positions)[3],
|
|
||||||
int totvert,
|
|
||||||
struct CustomData *vdata,
|
|
||||||
struct CustomData *ldata,
|
|
||||||
struct CustomData *pdata,
|
|
||||||
const struct MLoopTri *looptri,
|
|
||||||
int looptri_num);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do a full rebuild with on Grids data structure.
|
* Do a full rebuild with on Grids data structure.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2177,30 +2177,10 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
|
||||||
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide)
|
static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide)
|
||||||
{
|
{
|
||||||
Mesh *me = BKE_object_get_original_mesh(ob);
|
Mesh *me = BKE_object_get_original_mesh(ob);
|
||||||
const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
|
|
||||||
PBVH *pbvh = BKE_pbvh_new(PBVH_FACES);
|
PBVH *pbvh = BKE_pbvh_new(PBVH_FACES);
|
||||||
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
BKE_pbvh_respect_hide_set(pbvh, respect_hide);
|
||||||
|
|
||||||
MutableSpan<float3> positions = me->vert_positions_for_write();
|
BKE_pbvh_build_mesh(pbvh, me);
|
||||||
const blender::OffsetIndices polys = me->polys();
|
|
||||||
const Span<int> corner_verts = me->corner_verts();
|
|
||||||
|
|
||||||
MLoopTri *looptri = static_cast<MLoopTri *>(
|
|
||||||
MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__));
|
|
||||||
|
|
||||||
blender::bke::mesh::looptris_calc(positions, polys, corner_verts, {looptri, looptris_num});
|
|
||||||
|
|
||||||
BKE_pbvh_build_mesh(pbvh,
|
|
||||||
me,
|
|
||||||
polys,
|
|
||||||
corner_verts.data(),
|
|
||||||
reinterpret_cast<float(*)[3]>(positions.data()),
|
|
||||||
me->totvert,
|
|
||||||
&me->vdata,
|
|
||||||
&me->ldata,
|
|
||||||
&me->pdata,
|
|
||||||
looptri,
|
|
||||||
looptris_num);
|
|
||||||
|
|
||||||
const bool is_deformed = check_sculpt_object_deformed(ob, true);
|
const bool is_deformed = check_sculpt_object_deformed(ob, true);
|
||||||
if (is_deformed && me_eval_deform != nullptr) {
|
if (is_deformed && me_eval_deform != nullptr) {
|
||||||
|
|||||||
|
@ -2243,14 +2223,25 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
|
||||||
|
|
||||||
PBVH *pbvh = ob->sculpt->pbvh;
|
PBVH *pbvh = ob->sculpt->pbvh;
|
||||||
if (pbvh != nullptr) {
|
if (pbvh != nullptr) {
|
||||||
/* NOTE: It is possible that grids were re-allocated due to modifier
|
/* NOTE: It is possible that pointers to grids or other geometry data changed. Need to update
|
||||||
* stack. Need to update those pointers. */
|
* those pointers. */
|
||||||
if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
|
const PBVHType pbvh_type = BKE_pbvh_type(pbvh);
|
||||||
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
switch (pbvh_type) {
|
||||||
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
|
case PBVH_FACES: {
|
||||||
SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg;
|
BKE_pbvh_update_mesh_pointers(pbvh, BKE_object_get_original_mesh(ob));
|
||||||
if (subdiv_ccg != nullptr) {
|
break;
|
||||||
BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
|
}
|
||||||
|
case PBVH_GRIDS: {
|
||||||
|
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||||
|
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
|
||||||
|
SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg;
|
||||||
|
if (subdiv_ccg != nullptr) {
|
||||||
|
BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PBVH_BMESH: {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
|
|
||||||
#include "pbvh_intern.hh"
|
#include "pbvh_intern.hh"
|
||||||
|
|
||||||
|
using blender::float3;
|
||||||
|
using blender::MutableSpan;
|
||||||
|
using blender::Span;
|
||||||
|
|
||||||
#define LEAF_LIMIT 10000
|
#define LEAF_LIMIT 10000
|
||||||
|
|
||||||
/* Uncomment to test if triangles of the same face are
|
/* Uncomment to test if triangles of the same face are
|
||||||
|
@ -823,36 +827,58 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void BKE_pbvh_build_mesh(PBVH *pbvh,
|
void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
|
||||||
Mesh *mesh,
|
{
|
||||||
const blender::OffsetIndices<int> polys,
|
BLI_assert(pbvh->header.type == PBVH_FACES);
|
||||||
const int *corner_verts,
|
|
||||||
float (*vert_positions)[3],
|
pbvh->polys = mesh->polys();
|
||||||
int totvert,
|
pbvh->corner_verts = mesh->corner_verts().data();
|
||||||
CustomData *vdata,
|
if (!pbvh->deformed) {
|
||||||
CustomData *ldata,
|
/* Deformed positions not matching the original mesh are owned directly by the PBVH, and are
|
||||||
JacquesLucke marked this conversation as resolved
Outdated
Hans Goudey
commented
This comment is a bit confusing. I think a more correct phrasing would be This comment is a bit confusing. I think a more correct phrasing would be `Deformed positions not matching the original mesh are owned directly by the PBVH, and are set separately by #BKE_pbvh_vert_coords_apply` (though I do suggest tweaking that a bit below).
|
|||||||
CustomData *pdata,
|
* set separately by #BKE_pbvh_vert_coords_apply. */
|
||||||
const MLoopTri *looptri,
|
pbvh->vert_positions = BKE_mesh_vert_positions_for_write(mesh);
|
||||||
int looptri_num)
|
}
|
||||||
|
|
||||||
|
pbvh->material_indices = static_cast<const int *>(
|
||||||
|
CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, "material_index"));
|
||||||
|
pbvh->hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||||
|
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
||||||
|
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
||||||
|
&mesh->vdata, CD_PROP_BOOL, ".hide_vert", mesh->totvert));
|
||||||
|
|
||||||
|
/* Make sure cached normals start out calculated. */
|
||||||
|
mesh->vert_normals();
|
||||||
|
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
|
||||||
|
|
||||||
|
pbvh->vdata = &mesh->vdata;
|
||||||
|
pbvh->ldata = &mesh->ldata;
|
||||||
|
pbvh->pdata = &mesh->pdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
|
||||||
{
|
{
|
||||||
BBC *prim_bbc = nullptr;
|
BBC *prim_bbc = nullptr;
|
||||||
BB cb;
|
BB cb;
|
||||||
|
|
||||||
|
const int totvert = mesh->totvert;
|
||||||
|
const int looptri_num = poly_to_tri_count(mesh->totpoly, mesh->totloop);
|
||||||
|
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
|
||||||
|
const blender::OffsetIndices<int> polys = mesh->polys();
|
||||||
|
const Span<int> corner_verts = mesh->corner_verts();
|
||||||
|
|
||||||
|
MLoopTri *looptri = static_cast<MLoopTri *>(
|
||||||
|
MEM_malloc_arrayN(looptri_num, sizeof(*looptri), __func__));
|
||||||
|
|
||||||
|
blender::bke::mesh::looptris_calc(vert_positions, polys, corner_verts, {looptri, looptri_num});
|
||||||
|
|
||||||
pbvh->mesh = mesh;
|
pbvh->mesh = mesh;
|
||||||
pbvh->header.type = PBVH_FACES;
|
pbvh->header.type = PBVH_FACES;
|
||||||
pbvh->polys = polys;
|
|
||||||
pbvh->hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
BKE_pbvh_update_mesh_pointers(pbvh, mesh);
|
||||||
&mesh->pdata, CD_PROP_BOOL, ".hide_poly", mesh->totpoly));
|
|
||||||
pbvh->material_indices = static_cast<const int *>(
|
/* Those are not set in #BKE_pbvh_update_mesh_pointers because they are owned by the #PBVH. */
|
||||||
CustomData_get_layer_named(&mesh->pdata, CD_PROP_INT32, "material_index"));
|
|
||||||
pbvh->corner_verts = corner_verts;
|
|
||||||
pbvh->looptri = looptri;
|
pbvh->looptri = looptri;
|
||||||
pbvh->vert_positions = vert_positions;
|
|
||||||
/* Make sure cached normals start out calculated. */
|
|
||||||
mesh->vert_normals();
|
|
||||||
pbvh->vert_normals = BKE_mesh_vert_normals_for_write(mesh);
|
|
||||||
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
|
|
||||||
&mesh->vdata, CD_PROP_BOOL, ".hide_vert", mesh->totvert));
|
|
||||||
pbvh->vert_bitmap = static_cast<bool *>(
|
pbvh->vert_bitmap = static_cast<bool *>(
|
||||||
MEM_calloc_arrayN(totvert, sizeof(bool), "bvh->vert_bitmap"));
|
MEM_calloc_arrayN(totvert, sizeof(bool), "bvh->vert_bitmap"));
|
||||||
pbvh->totvert = totvert;
|
pbvh->totvert = totvert;
|
||||||
|
@ -866,9 +892,6 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
|
||||||
pbvh->leaf_limit = LEAF_LIMIT;
|
pbvh->leaf_limit = LEAF_LIMIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pbvh->vdata = vdata;
|
|
||||||
pbvh->ldata = ldata;
|
|
||||||
pbvh->pdata = pdata;
|
|
||||||
pbvh->faces_num = mesh->totpoly;
|
pbvh->faces_num = mesh->totpoly;
|
||||||
|
|
||||||
pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
|
pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
|
||||||
|
|
|
@ -160,6 +160,7 @@ struct PBVH {
|
||||||
/** Material indices. Only valid for polygon meshes. */
|
/** Material indices. Only valid for polygon meshes. */
|
||||||
const int *material_indices;
|
const int *material_indices;
|
||||||
const int *corner_verts;
|
const int *corner_verts;
|
||||||
|
/* Owned by the #PBVH, because after deformations they have to be recomputed. */
|
||||||
const MLoopTri *looptri;
|
const MLoopTri *looptri;
|
||||||
CustomData *vdata;
|
CustomData *vdata;
|
||||||
CustomData *ldata;
|
CustomData *ldata;
|
||||||
|
|
Loading…
Reference in New Issue
I wonder if it would make sense to check this before
BKE_pbvh_build_mesh
and giveBKE_pbvh_build_mesh
an optional argument for positions not owned by the mesh. That would go a long way to help clarify whetherPBVH
should reuse the arrays for the mesh's looptris and normals too, which is the biggest remaining pain point in this area IMO.Something similar would apply to
sculpt_update_object
, where the chunks of code currently callingBKE_pbvh_vert_coords_apply
could be moved to happen beforeBKE_sculpt_object_pbvh_ensure
(which would also get a new non-mesh positions argument).Not sure if you'd consider this related (feel free to disregard it). If not, I'll probably look into this in the near future.
Yeah that would probably improve the code even more, but won't integrate it into this patch.