Fix infinite loop bug
This commit is contained in:
parent
e07a95b86d
commit
ed15d0c1b9
|
@ -33,11 +33,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int64_t i;
|
||||
typedef struct SculptVertRef {
|
||||
intptr_t i;
|
||||
} SculptVertRef;
|
||||
|
||||
typedef SculptVertRef SculptFaceRef;
|
||||
typedef struct SculptFaceRef {
|
||||
intptr_t i;
|
||||
} SculptFaceRef;
|
||||
|
||||
BLI_INLINE SculptVertRef BKE_pbvh_make_vref(intptr_t i)
|
||||
{
|
||||
|
@ -51,6 +53,23 @@ BLI_INLINE SculptFaceRef BKE_pbvh_make_fref(intptr_t i)
|
|||
return ret;
|
||||
}
|
||||
|
||||
typedef struct PBVHTri {
|
||||
int v[3]; // references into PBVHTriBuf->verts
|
||||
|
||||
float no[3];
|
||||
SculptFaceRef f;
|
||||
} PBVHTri;
|
||||
|
||||
typedef struct PBVHTriBuf {
|
||||
PBVHTri *tris;
|
||||
SculptVertRef *verts;
|
||||
int tottri, totvert;
|
||||
|
||||
//private field
|
||||
intptr_t *loops;
|
||||
int totloop;
|
||||
} PBVHTriBuf;
|
||||
|
||||
struct BMLog;
|
||||
struct BMesh;
|
||||
struct BMVert;
|
||||
|
@ -175,7 +194,8 @@ typedef enum {
|
|||
PBVH_UpdateTopology = 1 << 13,
|
||||
PBVH_UpdateColor = 1 << 14,
|
||||
PBVH_Delete = 1 << 15,
|
||||
PBVH_UpdateCurvatureDir = 1 << 16
|
||||
PBVH_UpdateCurvatureDir = 1 << 16,
|
||||
PBVH_UpdateTris = 1 << 17
|
||||
} PBVHNodeFlags;
|
||||
|
||||
typedef struct PBVHFrustumPlanes {
|
||||
|
@ -234,10 +254,17 @@ void BKE_pbvh_free(PBVH *pbvh);
|
|||
|
||||
/** update original data, only data whose r_** parameters are passed in will be updated*/
|
||||
void BKE_pbvh_bmesh_update_origvert(
|
||||
PBVH *pbvh, struct BMVert *v, float **r_co, float **r_no, float **r_color);
|
||||
PBVH *pbvh, struct BMVert *v, float **r_co, float **r_no, float **r_color, bool log_undo);
|
||||
void BKE_pbvh_update_origcolor_bmesh(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_update_origco_bmesh(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
/**
|
||||
checks if original data needs to be updated for v, and if so updates it. Stroke_id
|
||||
is provided by the sculpt code and is used to detect updates. The reason we do it
|
||||
inside the verts and not in the nodes is to allow splitting of the pbvh during the stroke.
|
||||
*/
|
||||
bool BKE_pbvh_bmesh_check_origdata(PBVH *pbvh, struct BMVert *v, int stroke_id);
|
||||
|
||||
/* Hierarchical Search in the BVH, two methods:
|
||||
* - for each hit calling a callback
|
||||
* - gather nodes in an array (easy to multithread) */
|
||||
|
@ -261,7 +288,8 @@ void BKE_pbvh_raycast(PBVH *pbvh,
|
|||
void *data,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
bool original);
|
||||
bool original,
|
||||
int stroke_id);
|
||||
|
||||
bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
|
@ -273,9 +301,11 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
|||
float *depth,
|
||||
SculptVertRef *active_vertex_index,
|
||||
SculptFaceRef *active_face_grid_index,
|
||||
float *face_normal);
|
||||
float *face_normal,
|
||||
int stroke_id);
|
||||
|
||||
bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
|
||||
bool BKE_pbvh_bmesh_node_raycast_detail(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
float *depth,
|
||||
|
@ -300,7 +330,8 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
|
|||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
float *depth,
|
||||
float *dist_sq);
|
||||
float *dist_sq,
|
||||
int stroke_id);
|
||||
|
||||
/* Drawing */
|
||||
|
||||
|
@ -355,7 +386,7 @@ void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size, float detail_
|
|||
typedef enum {
|
||||
PBVH_Subdivide = 1,
|
||||
PBVH_Collapse = 2,
|
||||
PBVH_Cleanup = 4, //dissolve verts surrounded by either 3 or 4 triangles then triangulate
|
||||
PBVH_Cleanup = 4, // dissolve verts surrounded by either 3 or 4 triangles then triangulate
|
||||
} PBVHTopologyUpdateMode;
|
||||
bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
||||
PBVHTopologyUpdateMode mode,
|
||||
|
@ -422,7 +453,8 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *frustum);
|
|||
struct TableGSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
|
||||
struct TableGSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
|
||||
struct TableGSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
|
||||
void BKE_pbvh_bmesh_node_save_ortri(struct BMesh *bm, PBVHNode *node);
|
||||
|
||||
// now generated PBVHTris
|
||||
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
|
||||
|
||||
/* Update Bounding Box/Redraw and clear flags */
|
||||
|
@ -622,10 +654,6 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro
|
|||
void BKE_pbvh_node_free_proxies(PBVHNode *node);
|
||||
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot);
|
||||
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||
int (**r_orco_tris)[3],
|
||||
int *r_orco_tris_num,
|
||||
float (**r_orco_coords)[3]);
|
||||
|
||||
bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
|
@ -661,6 +689,10 @@ bool BKE_pbvh_curvature_update_get(PBVHNode *node);
|
|||
|
||||
int BKE_pbvh_get_totnodes(PBVH *pbvh);
|
||||
|
||||
void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node);
|
||||
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node);
|
||||
void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -250,7 +250,7 @@ void pbvh_grow_nodes(PBVH *pbvh, int totnode)
|
|||
|
||||
pbvh->totnode = totnode;
|
||||
|
||||
for (int i=0; i<pbvh->totnode; i++) {
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
PBVHNode *node = pbvh->nodes + i;
|
||||
|
||||
if (!node->id) {
|
||||
|
@ -1866,19 +1866,23 @@ void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
|
|||
node->flag |= PBVH_UpdateNormals | PBVH_UpdateCurvatureDir;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_mark_curvature_update(PBVHNode *node) {
|
||||
void BKE_pbvh_node_mark_curvature_update(PBVHNode *node)
|
||||
{
|
||||
node->flag |= PBVH_UpdateCurvatureDir;
|
||||
}
|
||||
|
||||
void BKE_pbvh_curvature_update_set(PBVHNode *node, bool state) {
|
||||
void BKE_pbvh_curvature_update_set(PBVHNode *node, bool state)
|
||||
{
|
||||
if (state) {
|
||||
node->flag |= PBVH_UpdateCurvatureDir;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
node->flag &= ~PBVH_UpdateCurvatureDir;
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_pbvh_curvature_update_get(PBVHNode *node) {
|
||||
bool BKE_pbvh_curvature_update_get(PBVHNode *node)
|
||||
{
|
||||
return node->flag & PBVH_UpdateCurvatureDir;
|
||||
}
|
||||
|
||||
|
@ -2073,16 +2077,6 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||
int (**r_orco_tris)[3],
|
||||
int *r_orco_tris_num,
|
||||
float (**r_orco_coords)[3])
|
||||
{
|
||||
*r_orco_tris = node->bm_ortri;
|
||||
*r_orco_tris_num = node->bm_tot_ortri;
|
||||
*r_orco_coords = node->bm_orco;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note doing a full search on all vertices here seems expensive,
|
||||
* however this is important to avoid having to recalculate bound-box & sync the buffers to the
|
||||
|
@ -2111,6 +2105,7 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node)
|
|||
typedef struct {
|
||||
struct IsectRayAABB_Precalc ray;
|
||||
bool original;
|
||||
int stroke_id;
|
||||
} RaycastData;
|
||||
|
||||
static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
|
||||
|
@ -2137,12 +2132,14 @@ void BKE_pbvh_raycast(PBVH *pbvh,
|
|||
void *data,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
bool original)
|
||||
bool original,
|
||||
int stroke_id)
|
||||
{
|
||||
RaycastData rcd;
|
||||
|
||||
isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal);
|
||||
rcd.original = original;
|
||||
rcd.stroke_id = stroke_id;
|
||||
|
||||
BKE_pbvh_search_callback_occluded(pbvh, ray_aabb_intersect, &rcd, cb, data);
|
||||
}
|
||||
|
@ -2431,7 +2428,8 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
|||
float *depth,
|
||||
SculptVertRef *active_vertex_index,
|
||||
SculptFaceRef *active_face_grid_index,
|
||||
float *face_normal)
|
||||
float *face_normal,
|
||||
int stroke_id)
|
||||
{
|
||||
bool hit = false;
|
||||
|
||||
|
@ -2466,7 +2464,9 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
|||
break;
|
||||
case PBVH_BMESH:
|
||||
// BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT);
|
||||
hit = pbvh_bmesh_node_raycast(node,
|
||||
|
||||
hit = pbvh_bmesh_node_raycast(pbvh,
|
||||
node,
|
||||
ray_start,
|
||||
ray_normal,
|
||||
isect_precalc,
|
||||
|
@ -2474,7 +2474,8 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
|
|||
use_origco,
|
||||
active_vertex_index,
|
||||
active_face_grid_index,
|
||||
face_normal);
|
||||
face_normal,
|
||||
stroke_id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2689,7 +2690,8 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
|
|||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
float *depth,
|
||||
float *dist_sq)
|
||||
float *dist_sq,
|
||||
int stroke_id)
|
||||
{
|
||||
bool hit = false;
|
||||
|
||||
|
@ -2708,7 +2710,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
|
|||
break;
|
||||
case PBVH_BMESH:
|
||||
hit = pbvh_bmesh_node_nearest_to_ray(
|
||||
node, ray_start, ray_normal, depth, dist_sq, use_origco);
|
||||
pbvh, node, ray_start, ray_normal, depth, dist_sq, use_origco, stroke_id);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3240,7 +3242,8 @@ int BKE_pbvh_get_node_index(PBVH *pbvh, PBVHNode *node)
|
|||
return (int)(node - pbvh->nodes);
|
||||
}
|
||||
|
||||
int BKE_pbvh_get_totnodes(PBVH *pbvh) {
|
||||
int BKE_pbvh_get_totnodes(PBVH *pbvh)
|
||||
{
|
||||
return pbvh->totnode;
|
||||
}
|
||||
|
||||
|
|
|
@ -308,10 +308,10 @@ static void pbvh_bmesh_node_finalize(PBVH *pbvh,
|
|||
BKE_pbvh_node_mark_rebuild_draw(n);
|
||||
|
||||
BKE_pbvh_node_fully_hidden_set(n, !has_visible);
|
||||
n->flag |= PBVH_UpdateNormals | PBVH_UpdateTopology | PBVH_UpdateCurvatureDir;
|
||||
n->flag |= PBVH_UpdateNormals | PBVH_UpdateTopology | PBVH_UpdateCurvatureDir | PBVH_UpdateTris;
|
||||
|
||||
if (add_orco) {
|
||||
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, n);
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,7 +515,7 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index)
|
|||
/* Likely this is already dirty. */
|
||||
pbvh->bm->elem_index_dirty |= BM_FACE;
|
||||
|
||||
pbvh_bmesh_node_split(pbvh, bbc_array, node_index, pbvh->nodes[node_index].bm_ortri != NULL, 0);
|
||||
pbvh_bmesh_node_split(pbvh, bbc_array, node_index, false, 0);
|
||||
|
||||
MEM_freeN(bbc_array);
|
||||
|
||||
|
@ -619,7 +619,7 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
|
|||
BLI_table_gset_insert(node->bm_unique_verts, v);
|
||||
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
|
||||
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_UpdateTris;
|
||||
|
||||
/* Log the new vertex */
|
||||
BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
|
||||
|
@ -659,7 +659,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *pbvh,
|
|||
BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
|
||||
|
||||
/* mark node for update */
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateTris;
|
||||
node->flag &= ~PBVH_FullyHidden;
|
||||
|
||||
/* Log the new face */
|
||||
|
@ -676,7 +676,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *pbvh,
|
|||
BLI_table_gset_add(node->bm_unique_verts, l->v);
|
||||
BM_ELEM_CD_SET_INT(l->v, cd_vert_node, node_index);
|
||||
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_UpdateTris;
|
||||
}
|
||||
else {
|
||||
BLI_table_gset_add(node->bm_other_verts, l->v);
|
||||
|
@ -831,7 +831,7 @@ static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
|
|||
f_node_index_prev = f_node_index;
|
||||
|
||||
PBVHNode *f_node = &pbvh->nodes[f_node_index];
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_UpdateTris;
|
||||
|
||||
/* Remove current ownership */
|
||||
BLI_table_gset_remove(f_node->bm_other_verts, v, NULL);
|
||||
|
@ -885,7 +885,7 @@ static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f)
|
|||
BM_log_face_removed(pbvh->bm_log, f);
|
||||
|
||||
/* mark node for update */
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateTris;
|
||||
}
|
||||
|
||||
static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
|
||||
|
@ -904,19 +904,6 @@ static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
|
|||
}
|
||||
}
|
||||
|
||||
static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
|
||||
{
|
||||
if (node->bm_orco) {
|
||||
MEM_freeN(node->bm_orco);
|
||||
}
|
||||
if (node->bm_ortri) {
|
||||
MEM_freeN(node->bm_ortri);
|
||||
}
|
||||
node->bm_orco = NULL;
|
||||
node->bm_ortri = NULL;
|
||||
node->bm_tot_ortri = 0;
|
||||
}
|
||||
|
||||
/****************************** EdgeQueue *****************************/
|
||||
|
||||
struct EdgeQueue;
|
||||
|
@ -2543,7 +2530,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
* note that we can often get-away without this but causes T48779 */
|
||||
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
|
||||
PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, l->f);
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB;
|
||||
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB |
|
||||
PBVH_UpdateTris;
|
||||
}
|
||||
BM_LOOPS_OF_VERT_ITER_END;
|
||||
}
|
||||
|
@ -2561,13 +2549,15 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
|
|||
}
|
||||
|
||||
void BKE_pbvh_bmesh_update_origvert(
|
||||
PBVH *pbvh, BMVert *v, float **r_co, float **r_no, float **r_color)
|
||||
PBVH *pbvh, BMVert *v, float **r_co, float **r_no, float **r_color, bool log_undo)
|
||||
{
|
||||
float *co = NULL, *no = NULL;
|
||||
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
|
||||
|
||||
BM_log_vert_before_modified(pbvh->bm_log, v, pbvh->cd_vert_mask_offset, r_color != NULL);
|
||||
if (log_undo) {
|
||||
BM_log_vert_before_modified(pbvh->bm_log, v, pbvh->cd_vert_mask_offset, r_color != NULL);
|
||||
}
|
||||
|
||||
if (r_co || r_no) {
|
||||
|
||||
|
@ -2707,7 +2697,23 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
|
|||
|
||||
/************************* Called from pbvh.c *************************/
|
||||
|
||||
bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
||||
bool BKE_pbvh_bmesh_check_origdata(PBVH *pbvh, BMVert *v, int stroke_id)
|
||||
{
|
||||
MDynTopoVert *mv = BKE_PBVH_DYNVERT(pbvh->cd_dyn_vert, v);
|
||||
|
||||
if (mv->stroke_id != stroke_id) {
|
||||
void *dummy;
|
||||
|
||||
BKE_pbvh_bmesh_update_origvert(pbvh, v, &dummy, &dummy, &dummy, false);
|
||||
mv->stroke_id = stroke_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pbvh_bmesh_node_raycast(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
|
@ -2715,57 +2721,83 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
|||
bool use_original,
|
||||
SculptVertRef *r_active_vertex_index,
|
||||
SculptFaceRef *r_active_face_index,
|
||||
float *r_face_normal)
|
||||
float *r_face_normal,
|
||||
int stroke_id)
|
||||
{
|
||||
bool hit = false;
|
||||
float nearest_vertex_co[3] = {0.0f};
|
||||
float nearest_vertex_dist = 1e17;
|
||||
|
||||
if (use_original && node->bm_tot_ortri) {
|
||||
for (int i = 0; i < node->bm_tot_ortri; i++) {
|
||||
const int *t = node->bm_ortri[i];
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
|
||||
bool hit2 = ray_face_intersection_tri(ray_start,
|
||||
isect_precalc,
|
||||
node->bm_orco[t[0]],
|
||||
node->bm_orco[t[1]],
|
||||
node->bm_orco[t[2]],
|
||||
depth);
|
||||
PBVHTriBuf *tribuf = node->tribuf;
|
||||
const int cd_dyn_vert = pbvh->cd_dyn_vert;
|
||||
|
||||
for (int i = 0; i < node->tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf->tris + i;
|
||||
BMVert *v1 = (BMVert *)tribuf->verts[tri->v[0]].i;
|
||||
BMVert *v2 = (BMVert *)tribuf->verts[tri->v[1]].i;
|
||||
BMVert *v3 = (BMVert *)tribuf->verts[tri->v[2]].i;
|
||||
|
||||
BMFace *f = (BMFace *)tri->f.i;
|
||||
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float *co1, *co2, *co3;
|
||||
|
||||
if (use_original) {
|
||||
BKE_pbvh_bmesh_check_origdata(pbvh, v1, stroke_id);
|
||||
BKE_pbvh_bmesh_check_origdata(pbvh, v2, stroke_id);
|
||||
BKE_pbvh_bmesh_check_origdata(pbvh, v3, stroke_id);
|
||||
|
||||
co1 = BKE_PBVH_DYNVERT(cd_dyn_vert, v1)->origco;
|
||||
co2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v2)->origco;
|
||||
co3 = BKE_PBVH_DYNVERT(cd_dyn_vert, v3)->origco;
|
||||
}
|
||||
else {
|
||||
co1 = v1->co;
|
||||
co2 = v2->co;
|
||||
co3 = v3->co;
|
||||
}
|
||||
bool hit2 = ray_face_intersection_tri(ray_start, isect_precalc, co1, co2, co3, depth);
|
||||
|
||||
if (hit2) {
|
||||
// ensure sculpt active vertex is set r_active_vertex_index
|
||||
if (hit2) {
|
||||
int k = 0;
|
||||
BMFace *f = NULL;
|
||||
|
||||
TGSET_ITER_INDEX(f, node->bm_faces, k)
|
||||
{
|
||||
if (k == i) {
|
||||
break;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
BMVert *v = (BMVert *)tribuf->verts[tri->v[j]].i;
|
||||
float *co = BKE_PBVH_DYNVERT(cd_dyn_vert, v)->origco;
|
||||
|
||||
float dist = len_squared_v3v3(co, ray_start);
|
||||
if (dist < nearest_vertex_dist) {
|
||||
nearest_vertex_dist = dist;
|
||||
copy_v3_v3(nearest_vertex_co, co);
|
||||
|
||||
hit = true;
|
||||
if (r_active_vertex_index) {
|
||||
*r_active_vertex_index = tribuf->verts[tri->v[j]];
|
||||
}
|
||||
}
|
||||
TGSET_ITER_INDEX_END
|
||||
|
||||
if (!f) {
|
||||
continue;
|
||||
}
|
||||
if (r_active_face_index) {
|
||||
*r_active_face_index = tri->f;
|
||||
}
|
||||
|
||||
BMLoop *l = f->l_first;
|
||||
if (r_face_normal) {
|
||||
float no[3];
|
||||
|
||||
for (int j = 0; j < 3; j++, l = l->next) {
|
||||
float dist = len_squared_v3v3(node->bm_orco[t[j]], ray_start);
|
||||
|
||||
if (!hit || dist < len_squared_v3v3(ray_start, nearest_vertex_co)) {
|
||||
int idx = t[j];
|
||||
|
||||
hit = true;
|
||||
copy_v3_v3(nearest_vertex_co, node->bm_orco[t[j]]);
|
||||
|
||||
if (r_active_vertex_index) {
|
||||
*r_active_vertex_index = BKE_pbvh_make_vref((intptr_t)l->v);
|
||||
if (use_original) {
|
||||
copy_v3_v3(no, BKE_PBVH_DYNVERT(cd_dyn_vert, v1)->origno);
|
||||
add_v3_v3(no, BKE_PBVH_DYNVERT(cd_dyn_vert, v2)->origno);
|
||||
add_v3_v3(no, BKE_PBVH_DYNVERT(cd_dyn_vert, v3)->origno);
|
||||
normalize_v3(no);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(no, tri->no);
|
||||
}
|
||||
|
||||
if (r_active_face_index) {
|
||||
*r_active_face_index = BKE_pbvh_make_fref((intptr_t)l->f);
|
||||
}
|
||||
copy_v3_v3(r_face_normal, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2773,133 +2805,99 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
|||
hit = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMFace *f;
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BLI_assert(f->len == 3);
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
BMVert *v_tri[3];
|
||||
|
||||
BM_face_as_array_vert_tri(f, v_tri);
|
||||
bool hit2;
|
||||
|
||||
if (hit2 = ray_face_intersection_tri(
|
||||
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
|
||||
|
||||
if (r_face_normal) {
|
||||
normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
|
||||
}
|
||||
|
||||
if (r_active_vertex_index) {
|
||||
float location[3] = {0.0f};
|
||||
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (!hit || len_squared_v3v3(location, v_tri[j]->co) <
|
||||
len_squared_v3v3(location, nearest_vertex_co)) {
|
||||
copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
|
||||
SculptVertRef vref = {(intptr_t)v_tri[j]}; // BM_elem_index_get(v_tri[j]);
|
||||
*r_active_vertex_index = vref;
|
||||
|
||||
if (r_active_face_index) {
|
||||
*r_active_face_index = BKE_pbvh_make_fref((intptr_t)f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
|
||||
bool BKE_pbvh_bmesh_node_raycast_detail(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
float *depth,
|
||||
float *r_edge_length)
|
||||
{
|
||||
if (node->flag & PBVH_FullyHidden) {
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
BMFace *f;
|
||||
bool hit = false;
|
||||
BMFace *f_hit = NULL;
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BLI_assert(f->len == 3);
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
for (int i = 0; i < node->tribuf->tottri; i++) {
|
||||
PBVHTri *tri = node->tribuf + i;
|
||||
BMVert *v1 = (BMVert *)node->tribuf->verts[tri->v[0]].i;
|
||||
BMVert *v2 = (BMVert *)node->tribuf->verts[tri->v[1]].i;
|
||||
BMVert *v3 = (BMVert *)node->tribuf->verts[tri->v[2]].i;
|
||||
BMFace *f = (BMFace *)tri->f.i;
|
||||
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
BMVert *v_tri[3];
|
||||
bool hit_local;
|
||||
BM_face_as_array_vert_tri(f, v_tri);
|
||||
hit_local = ray_face_intersection_tri(
|
||||
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth);
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hit_local) {
|
||||
f_hit = f;
|
||||
hit = true;
|
||||
}
|
||||
bool hit_local = ray_face_intersection_tri(
|
||||
ray_start, isect_precalc, v1->co, v2->co, v3->co, depth);
|
||||
|
||||
if (hit_local) {
|
||||
float len1 = len_squared_v3v3(v1->co, v2->co);
|
||||
float len2 = len_squared_v3v3(v2->co, v3->co);
|
||||
float len3 = len_squared_v3v3(v3->co, v1->co);
|
||||
|
||||
/* detail returned will be set to the maximum allowed size, so take max here */
|
||||
*r_edge_length = sqrtf(max_fff(len1, len2, len3));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
if (hit) {
|
||||
BMVert *v_tri[3];
|
||||
BM_face_as_array_vert_tri(f_hit, v_tri);
|
||||
float len1 = len_squared_v3v3(v_tri[0]->co, v_tri[1]->co);
|
||||
float len2 = len_squared_v3v3(v_tri[1]->co, v_tri[2]->co);
|
||||
float len3 = len_squared_v3v3(v_tri[2]->co, v_tri[0]->co);
|
||||
|
||||
/* detail returned will be set to the maximum allowed size, so take max here */
|
||||
*r_edge_length = sqrtf(max_fff(len1, len2, len3));
|
||||
}
|
||||
|
||||
return hit;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
|
||||
bool pbvh_bmesh_node_nearest_to_ray(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
float *depth,
|
||||
float *dist_sq,
|
||||
bool use_original)
|
||||
bool use_original,
|
||||
int stroke_id)
|
||||
{
|
||||
bool hit = false;
|
||||
|
||||
if (use_original && node->bm_tot_ortri) {
|
||||
for (int i = 0; i < node->bm_tot_ortri; i++) {
|
||||
const int *t = node->bm_ortri[i];
|
||||
hit |= ray_face_nearest_tri(ray_start,
|
||||
ray_normal,
|
||||
node->bm_orco[t[0]],
|
||||
node->bm_orco[t[1]],
|
||||
node->bm_orco[t[2]],
|
||||
depth,
|
||||
dist_sq);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMFace *f;
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
PBVHTriBuf *tribuf = node->tribuf;
|
||||
const int cd_dyn_vert = pbvh->cd_dyn_vert;
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BLI_assert(f->len == 3);
|
||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
BMVert *v_tri[3];
|
||||
for (int i = 0; i < tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf + i;
|
||||
BMFace *f = (BMFace *)tri->f.i;
|
||||
|
||||
BM_face_as_array_vert_tri(f, v_tri);
|
||||
hit |= ray_face_nearest_tri(
|
||||
ray_start, ray_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth, dist_sq);
|
||||
}
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
BMVert *v1 = (BMVert *)tribuf->verts[tri->v[0]].i;
|
||||
BMVert *v2 = (BMVert *)tribuf->verts[tri->v[1]].i;
|
||||
BMVert *v3 = (BMVert *)tribuf->verts[tri->v[2]].i;
|
||||
|
||||
float *co1, *co2, *co3;
|
||||
|
||||
if (use_original) {
|
||||
BKE_pbvh_bmesh_check_origdata(pbvh, v1, stroke_id);
|
||||
BKE_pbvh_bmesh_check_origdata(pbvh, v2, stroke_id);
|
||||
BKE_pbvh_bmesh_check_origdata(pbvh, v3, stroke_id);
|
||||
|
||||
co1 = BKE_PBVH_DYNVERT(cd_dyn_vert, v1)->origco;
|
||||
co2 = BKE_PBVH_DYNVERT(cd_dyn_vert, v2)->origco;
|
||||
co3 = BKE_PBVH_DYNVERT(cd_dyn_vert, v3)->origco;
|
||||
}
|
||||
else {
|
||||
co1 = v1->co;
|
||||
co2 = v2->co;
|
||||
co3 = v3->co;
|
||||
}
|
||||
|
||||
hit |= ray_face_nearest_tri(ray_start, ray_normal, co1, co2, co3, depth, dist_sq);
|
||||
}
|
||||
|
||||
return hit;
|
||||
|
@ -3122,7 +3120,7 @@ static void pbvh_bmesh_create_nodes_fast_recursive(
|
|||
|
||||
bool has_visible = false;
|
||||
|
||||
n->flag = PBVH_Leaf;
|
||||
n->flag = PBVH_Leaf | PBVH_UpdateTris;
|
||||
n->bm_faces = BLI_table_gset_new_ex("bm_faces", node->totface);
|
||||
|
||||
/* Create vert hash sets */
|
||||
|
@ -3318,7 +3316,6 @@ bool BKE_pbvh_bmesh_update_topology_nodes(PBVH *pbvh,
|
|||
undopush(node, searchdata);
|
||||
|
||||
BKE_pbvh_node_mark_topology_update(pbvh->nodes + i);
|
||||
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, pbvh->nodes + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3612,24 +3609,21 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
//avoid potential infinite loops
|
||||
const int totnode = pbvh->totnode;
|
||||
|
||||
for (int i = 0; i < totnode; i++) {
|
||||
PBVHNode *node = pbvh->nodes + i;
|
||||
|
||||
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
|
||||
!(node->flag & PBVH_FullyHidden)) {
|
||||
node->flag &= ~PBVH_UpdateTopology;
|
||||
|
||||
pbvh_bmesh_node_drop_orig(node);
|
||||
node->flag &= ~PBVH_UpdateTopology;
|
||||
|
||||
/* Recursively split nodes that have gotten too many
|
||||
* elements */
|
||||
if (updatePBVH) {
|
||||
if (!pbvh_bmesh_node_limit_ensure(pbvh, i)) {
|
||||
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, pbvh->nodes + i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, pbvh->nodes + i);
|
||||
pbvh_bmesh_node_limit_ensure(pbvh, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3654,77 +3648,224 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
|||
return modified;
|
||||
}
|
||||
|
||||
PBVHTriBuf *BKE_pbvh_bmesh_get_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
BKE_pbvh_bmesh_check_tris(pbvh, node);
|
||||
|
||||
return node->tribuf;
|
||||
}
|
||||
|
||||
void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
if (node->tribuf) {
|
||||
MEM_SAFE_FREE(node->tribuf->verts);
|
||||
MEM_SAFE_FREE(node->tribuf->tris);
|
||||
MEM_SAFE_FREE(node->tribuf->loops);
|
||||
MEM_freeN(node->tribuf);
|
||||
node->tribuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
generate triangle buffers with split uv islands.
|
||||
currently unused (and untested).
|
||||
*/
|
||||
static bool pbvh_bmesh_split_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
BMFace *f;
|
||||
|
||||
BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT | BM_FACE);
|
||||
|
||||
// split by uvs
|
||||
int layeri = CustomData_get_layer_index(&pbvh->bm->ldata, CD_MLOOPUV);
|
||||
if (layeri < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int totlayer = 0;
|
||||
|
||||
while (layeri < pbvh->bm->ldata.totlayer && pbvh->bm->ldata.layers[layeri].type == CD_MLOOPUV) {
|
||||
totlayer++;
|
||||
layeri++;
|
||||
}
|
||||
|
||||
const int cd_uv = pbvh->bm->ldata.layers[layeri].offset;
|
||||
const int cd_size = CustomData_sizeof(CD_MLOOPUV);
|
||||
|
||||
SculptVertRef *verts = NULL;
|
||||
PBVHTri *tris = NULL;
|
||||
intptr_t *loops = NULL;
|
||||
|
||||
BLI_array_declare(verts);
|
||||
BLI_array_declare(tris);
|
||||
BLI_array_declare(loops);
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
l->head.index = -1;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
int vi = 0;
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
if (l->head.index >= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
l->head.index = vi++;
|
||||
BLI_array_append(loops, (intptr_t)l);
|
||||
|
||||
SculptVertRef sv = {(intptr_t)l->v};
|
||||
BLI_array_append(verts, sv);
|
||||
|
||||
BMIter iter;
|
||||
BMLoop *l2;
|
||||
|
||||
BM_ITER_ELEM (l2, &iter, l, BM_LOOPS_OF_VERT) {
|
||||
bool ok = true;
|
||||
|
||||
for (int i = 0; i < totlayer; i++) {
|
||||
MLoopUV *uv1 = BM_ELEM_CD_GET_VOID_P(l, cd_uv + cd_size * i);
|
||||
MLoopUV *uv2 = BM_ELEM_CD_GET_VOID_P(l2, cd_uv + cd_size * i);
|
||||
|
||||
if (len_v3v3(uv1, uv2) > 0.001) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
l2->head.index = l->head.index;
|
||||
}
|
||||
}
|
||||
} while (l != f->l_first);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
BMLoop *l1 = f->l_first, *l2 = f->l_first->next, *l3 = f->l_first->prev;
|
||||
|
||||
PBVHTri tri;
|
||||
tri.f.i = (intptr_t)f;
|
||||
|
||||
tri.v[0] = l1->head.index;
|
||||
tri.v[1] = l2->head.index;
|
||||
tri.v[2] = l3->head.index;
|
||||
|
||||
copy_v3_v3(tri.no, f->no);
|
||||
BLI_array_append(tris, tri);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
if (node->tribuf) {
|
||||
MEM_SAFE_FREE(node->tribuf->verts);
|
||||
MEM_SAFE_FREE(node->tribuf->tris);
|
||||
MEM_SAFE_FREE(node->tribuf->loops);
|
||||
|
||||
node->tribuf->tottri = 0;
|
||||
node->tribuf->tris = NULL;
|
||||
}
|
||||
else {
|
||||
node->tribuf = MEM_callocN(sizeof(*node->tribuf), "node->tribuf");
|
||||
}
|
||||
|
||||
node->tribuf->verts = verts;
|
||||
node->tribuf->loops = loops;
|
||||
node->tribuf->tris = tris;
|
||||
|
||||
node->tribuf->tottri = BLI_array_len(tris);
|
||||
node->tribuf->totvert = BLI_array_len(verts);
|
||||
node->tribuf->totloop = BLI_array_len(loops);
|
||||
|
||||
return true;
|
||||
}
|
||||
/* In order to perform operations on the original node coordinates
|
||||
* (currently just raycast), store the node's triangles and vertices.
|
||||
*
|
||||
* Skips triangles that are hidden. */
|
||||
void BKE_pbvh_bmesh_node_save_ortri(BMesh *bm, PBVHNode *node)
|
||||
void BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
|
||||
{
|
||||
/* Skip if original coords/triangles are already saved */
|
||||
if (node->bm_orco) {
|
||||
BMesh *bm = pbvh->bm;
|
||||
|
||||
if (!(node->flag & PBVH_UpdateTris) && node->tribuf) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int totvert = BLI_table_gset_len(node->bm_unique_verts) +
|
||||
BLI_table_gset_len(node->bm_other_verts);
|
||||
if (node->tribuf) {
|
||||
MEM_SAFE_FREE(node->tribuf->verts);
|
||||
MEM_SAFE_FREE(node->tribuf->tris);
|
||||
MEM_SAFE_FREE(node->tribuf->loops);
|
||||
|
||||
const int tottri = BLI_table_gset_len(node->bm_faces);
|
||||
|
||||
node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
|
||||
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __func__);
|
||||
|
||||
/* Copy out the vertices and assign a temporary index */
|
||||
int i = 0;
|
||||
BMVert *v;
|
||||
TGSET_ITER (v, node->bm_unique_verts) {
|
||||
copy_v3_v3(node->bm_orco[i], v->co);
|
||||
BM_elem_index_set(v, i); /* set_dirty! */
|
||||
i++;
|
||||
node->tribuf->tottri = 0;
|
||||
node->tribuf->totvert = 0;
|
||||
node->tribuf->totloop = 0;
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
TGSET_ITER (v, node->bm_other_verts) {
|
||||
copy_v3_v3(node->bm_orco[i], v->co);
|
||||
BM_elem_index_set(v, i); /* set_dirty! */
|
||||
i++;
|
||||
else {
|
||||
node->tribuf = MEM_callocN(sizeof(*node->tribuf), "node->tribuf");
|
||||
node->tribuf->loops = NULL;
|
||||
node->tribuf->totloop = 0;
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
/* Likely this is already dirty. */
|
||||
bm->elem_index_dirty |= BM_VERT;
|
||||
node->flag &= ~PBVH_UpdateTris;
|
||||
PBVHTri *tris = NULL;
|
||||
SculptVertRef *verts = NULL;
|
||||
|
||||
/* Copy the triangles */
|
||||
i = 0;
|
||||
BLI_array_declare(tris);
|
||||
BLI_array_declare(verts);
|
||||
|
||||
GHash *vmap = BLI_ghash_ptr_new("pbvh_bmesh.c vmap");
|
||||
BMFace *f;
|
||||
|
||||
TGSET_ITER (f, node->bm_faces) {
|
||||
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
BMVert *v1 = f->l_first->v;
|
||||
BMVert *v2 = f->l_first->next->v;
|
||||
BMVert *v3 = f->l_first->prev->v;
|
||||
|
||||
#if 0
|
||||
if (f->l_first->v->head.index >= totvert || f->l_first->next->v->head.index >= totvert ||
|
||||
f->l_first->prev->v->head.index >= totvert) {
|
||||
printf("Error!\n");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
PBVHTri tri = {0};
|
||||
|
||||
#if 0
|
||||
BMIter bm_iter;
|
||||
BMVert *v;
|
||||
BMLoop *l = f->l_first;
|
||||
int j = 0;
|
||||
BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) {
|
||||
node->bm_ortri[i][j] = BM_elem_index_get(v);
|
||||
|
||||
do {
|
||||
void **val = NULL;
|
||||
|
||||
if (!BLI_ghash_ensure_p(vmap, l->v, &val)) {
|
||||
SculptVertRef sv = {(intptr_t)l->v};
|
||||
|
||||
*val = (void*) BLI_array_len(verts);
|
||||
BLI_array_append(verts, sv);
|
||||
|
||||
}
|
||||
|
||||
tri.v[j] = (intptr_t) val[0];
|
||||
|
||||
j++;
|
||||
}
|
||||
#else
|
||||
bm_face_as_array_index_tri(f, node->bm_ortri[i]);
|
||||
#endif
|
||||
i++;
|
||||
l = l->next;
|
||||
} while (l != f->l_first);
|
||||
|
||||
copy_v3_v3(tri.no, f->no);
|
||||
tri.f.i = (intptr_t)f;
|
||||
|
||||
BLI_array_append(tris, tri);
|
||||
}
|
||||
TGSET_ITER_END
|
||||
|
||||
node->bm_tot_ortri = i;
|
||||
bm->elem_index_dirty | BM_VERT;
|
||||
|
||||
node->tribuf->tris = tris;
|
||||
node->tribuf->tottri = BLI_array_len(tris);
|
||||
node->tribuf->verts = verts;
|
||||
node->tribuf->totvert = BLI_array_len(verts);
|
||||
|
||||
BLI_ghash_free(vmap, NULL, NULL);
|
||||
}
|
||||
|
||||
static int pbvh_count_subtree_verts(PBVH *pbvh, PBVHNode *n)
|
||||
|
@ -3812,7 +3953,7 @@ static void BKE_pbvh_bmesh_corect_tree(PBVH *pbvh, PBVHNode *node, PBVHNode *par
|
|||
node->flag |= PBVH_Leaf | PBVH_UpdateRedraw | PBVH_UpdateBB | PBVH_UpdateDrawBuffers |
|
||||
PBVH_RebuildDrawBuffers | PBVH_UpdateOriginalBB | PBVH_UpdateMask |
|
||||
PBVH_UpdateVisibility | PBVH_UpdateColor | PBVH_UpdateTopology |
|
||||
PBVH_UpdateNormals;
|
||||
PBVH_UpdateNormals | PBVH_UpdateTris;
|
||||
|
||||
TableGSet *other = BLI_table_gset_new(__func__);
|
||||
BMVert *v;
|
||||
|
@ -3890,14 +4031,14 @@ static void pbvh_bmesh_join_nodes(PBVH *bvh)
|
|||
printf("un-deleting an empty node\n");
|
||||
PBVHNode *n3 = n1->flag & PBVH_Delete ? n1 : n2;
|
||||
|
||||
n3->flag = PBVH_Leaf;
|
||||
n3->flag = PBVH_Leaf | PBVH_UpdateTris;
|
||||
n3->bm_unique_verts = BLI_table_gset_new("bm_unique_verts");
|
||||
n3->bm_other_verts = BLI_table_gset_new("bm_other_verts");
|
||||
n3->bm_faces = BLI_table_gset_new("bm_faces");
|
||||
}
|
||||
else if ((n1->flag & PBVH_Delete) && (n2->flag & PBVH_Delete)) {
|
||||
n->children_offset = 0;
|
||||
n->flag |= PBVH_Leaf;
|
||||
n->flag |= PBVH_Leaf | PBVH_UpdateTris;
|
||||
|
||||
if (!n->bm_unique_verts) {
|
||||
// should not happen
|
||||
|
@ -3940,14 +4081,8 @@ static void pbvh_bmesh_join_nodes(PBVH *bvh)
|
|||
n->face_vert_indices = NULL;
|
||||
}
|
||||
|
||||
if (n->bm_orco) {
|
||||
MEM_freeN(n->bm_orco);
|
||||
n->bm_orco = NULL;
|
||||
}
|
||||
|
||||
if (n->bm_ortri) {
|
||||
MEM_freeN(n->bm_ortri);
|
||||
n->bm_ortri = NULL;
|
||||
if (n->tribuf) {
|
||||
BKE_pbvh_bmesh_free_tris(bvh, n);
|
||||
}
|
||||
|
||||
if (n->bm_unique_verts) {
|
||||
|
@ -4086,11 +4221,15 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
|
|||
check_heap();
|
||||
int totnode = pbvh->totnode;
|
||||
|
||||
// pbvh_bmesh_join_nodes(pbvh);
|
||||
pbvh_bmesh_join_nodes(pbvh);
|
||||
|
||||
check_heap();
|
||||
|
||||
for (int i = 0; i < pbvh->totnode; i++) {
|
||||
BKE_pbvh_update_bounds(pbvh, (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw));
|
||||
|
||||
totnode = pbvh->totnode;
|
||||
|
||||
for (int i = 0; i < totnode; i++) {
|
||||
PBVHNode *n = pbvh->nodes + i;
|
||||
|
||||
if (totnode != pbvh->totnode) {
|
||||
|
@ -4100,18 +4239,11 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
|
|||
}
|
||||
|
||||
if (n->flag & PBVH_Leaf) {
|
||||
/* Free orco/ortri data */
|
||||
pbvh_bmesh_node_drop_orig(n);
|
||||
|
||||
/* Recursively split nodes that have gotten too many
|
||||
* elements */
|
||||
if (!pbvh_bmesh_node_limit_ensure(pbvh, i)) {
|
||||
BKE_pbvh_bmesh_node_save_ortri(pbvh->bm, n);
|
||||
}
|
||||
pbvh_bmesh_node_limit_ensure(pbvh, i);
|
||||
}
|
||||
}
|
||||
|
||||
BKE_pbvh_update_bounds(pbvh, (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw));
|
||||
}
|
||||
|
||||
void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size, float detail_range)
|
||||
|
|
|
@ -106,9 +106,8 @@ struct PBVHNode {
|
|||
TableGSet *bm_faces;
|
||||
TableGSet *bm_unique_verts;
|
||||
TableGSet *bm_other_verts;
|
||||
float (*bm_orco)[3];
|
||||
int (*bm_ortri)[3];
|
||||
int bm_tot_ortri;
|
||||
|
||||
PBVHTriBuf *tribuf;
|
||||
|
||||
/* Used to store the brush color during a stroke and composite it over the original color */
|
||||
PBVHColorBufferNode color_buffer;
|
||||
|
@ -235,20 +234,25 @@ bool ray_face_nearest_tri(const float ray_start[3],
|
|||
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
|
||||
|
||||
/* pbvh_bmesh.c */
|
||||
bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
||||
bool pbvh_bmesh_node_raycast(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
struct IsectRayPrecalc *isect_precalc,
|
||||
float *dist,
|
||||
bool use_original,
|
||||
SculptVertRef *r_active_vertex_index,
|
||||
SculptFaceRef *r_active_face_index,
|
||||
float *r_face_normal);
|
||||
bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
|
||||
struct SculptVertRef *r_active_vertex_index,
|
||||
struct SculptFaceRef *r_active_face_index,
|
||||
float *r_face_normal,
|
||||
int stroke_id);
|
||||
|
||||
bool pbvh_bmesh_node_nearest_to_ray(PBVH *pbvh,
|
||||
PBVHNode *node,
|
||||
const float ray_start[3],
|
||||
const float ray_normal[3],
|
||||
float *depth,
|
||||
float *dist_sq,
|
||||
bool use_original);
|
||||
bool use_original,
|
||||
int stroke_id);
|
||||
|
||||
void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode);
|
||||
|
|
|
@ -131,6 +131,17 @@ int SCULPT_vertex_count_get(SculptSession *ss)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex)
|
||||
{
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
|
||||
BMVert *v = (BMVert *)vertex.i;
|
||||
return BKE_PBVH_DYNVERT(ss->cd_dyn_vert, v)->origco;
|
||||
}
|
||||
|
||||
// XXX implement me
|
||||
return SCULPT_vertex_co_get(ss, vertex);
|
||||
}
|
||||
|
||||
const float *SCULPT_vertex_co_get(SculptSession *ss, SculptVertRef index)
|
||||
{
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
|
@ -1851,16 +1862,17 @@ static void sculpt_project_v3(const SculptProjectVector *spvc, const float vec[3
|
|||
* Same goes for alt-key smoothing. */
|
||||
bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *brush)
|
||||
{
|
||||
return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
|
||||
return (
|
||||
(BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) &&
|
||||
|
||||
(!ss->cache || (!ss->cache->alt_smooth)) &&
|
||||
(!ss->cache || (!ss->cache->alt_smooth)) &&
|
||||
|
||||
/* Requires mesh restore, which doesn't work with
|
||||
* dynamic-topology. */
|
||||
!(brush->flag & BRUSH_ANCHORED) && !(brush->flag & BRUSH_DRAG_DOT) &&
|
||||
(brush->cached_dyntopo.flag & (DYNTOPO_SUBDIVIDE | DYNTOPO_COLLAPSE | DYNTOPO_CLEANUP)) &&
|
||||
!(brush->cached_dyntopo.flag & DYNTOPO_DISABLED) &&
|
||||
SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool));
|
||||
/* Requires mesh restore, which doesn't work with
|
||||
* dynamic-topology. */
|
||||
!(brush->flag & BRUSH_ANCHORED) && !(brush->flag & BRUSH_DRAG_DOT) &&
|
||||
(brush->cached_dyntopo.flag & (DYNTOPO_SUBDIVIDE | DYNTOPO_COLLAPSE | DYNTOPO_CLEANUP)) &&
|
||||
!(brush->cached_dyntopo.flag & DYNTOPO_DISABLED) &&
|
||||
SCULPT_TOOL_HAS_DYNTOPO(brush->sculpt_tool));
|
||||
}
|
||||
|
||||
/*** paint mesh ***/
|
||||
|
@ -2341,8 +2353,7 @@ typedef struct AreaNormalCenterTLSData {
|
|||
int count_co[2];
|
||||
} AreaNormalCenterTLSData;
|
||||
|
||||
static void calc_area_normal_and_center_task_cb(
|
||||
void *__restrict userdata,
|
||||
static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
||||
const int n,
|
||||
const TaskParallelTLS *__restrict tls)
|
||||
{
|
||||
|
@ -2404,13 +2415,18 @@ static void calc_area_normal_and_center_task_cb(
|
|||
int(*orco_tris)[3];
|
||||
int orco_tris_num;
|
||||
|
||||
BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords);
|
||||
PBVHTriBuf *tribuf = BKE_pbvh_bmesh_get_tris(ss->pbvh, data->nodes[n]);
|
||||
|
||||
for (int i = 0; i < orco_tris_num; i++) {
|
||||
const float *co_tri[3] = {
|
||||
orco_coords[orco_tris[i][0]],
|
||||
orco_coords[orco_tris[i][1]],
|
||||
orco_coords[orco_tris[i][2]],
|
||||
for (int i = 0; i < tribuf->tottri; i++) {
|
||||
PBVHTri *tri = tribuf->tris + i;
|
||||
SculptVertRef v1 = tribuf->verts[tri->v[0]];
|
||||
SculptVertRef v2 = tribuf->verts[tri->v[1]];
|
||||
SculptVertRef v3 = tribuf->verts[tri->v[2]];
|
||||
|
||||
const float(*co_tri[3]) = {
|
||||
SCULPT_vertex_origco_get(ss, v1),
|
||||
SCULPT_vertex_origco_get(ss, v2),
|
||||
SCULPT_vertex_origco_get(ss, v3),
|
||||
};
|
||||
float co[3];
|
||||
|
||||
|
@ -5270,7 +5286,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
|
||||
cd_layer_disp = SCULPT_dyntopo_get_templayer(ss, CD_PROP_FLOAT, SCULPT_LAYER_DISP);
|
||||
|
||||
//should never happen
|
||||
// should never happen
|
||||
if (cd_pers_co < 0 || cd_pers_no < 0 || cd_pers_disp < 0 || cd_layer_disp < 0) {
|
||||
printf("error!! $d $d $d $d\n", cd_pers_co, cd_pers_no, cd_pers_disp, cd_layer_disp);
|
||||
return;
|
||||
|
@ -5285,7 +5301,7 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
|
||||
SculptThreadedTaskData data = {
|
||||
.sd = sd,
|
||||
.ob = ob,
|
||||
.ob = ob,
|
||||
.brush = brush,
|
||||
.nodes = nodes,
|
||||
.cd_pers_co = cd_pers_co,
|
||||
|
@ -6532,7 +6548,8 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
|
|||
|
||||
BKE_pbvh_node_mark_update(nodes[i]);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < totnode; i++) {
|
||||
SCULPT_ensure_dyntopo_node_undo(ob, nodes[i], SCULPT_UNDO_COORDS, -1);
|
||||
BKE_pbvh_node_mark_update(nodes[i]);
|
||||
|
@ -7947,7 +7964,8 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
|
|||
&srd->depth,
|
||||
&srd->active_vertex_index,
|
||||
&srd->active_face_grid_index,
|
||||
srd->face_normal)) {
|
||||
srd->face_normal,
|
||||
srd->ss->stroke_id)) {
|
||||
srd->hit = true;
|
||||
*tmin = srd->depth;
|
||||
}
|
||||
|
@ -7981,7 +7999,8 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
|
|||
srd->ray_start,
|
||||
srd->ray_normal,
|
||||
&srd->depth,
|
||||
&srd->dist_sq_to_ray)) {
|
||||
&srd->dist_sq_to_ray,
|
||||
srd->ss->stroke_id)) {
|
||||
srd->hit = true;
|
||||
*tmin = srd->dist_sq_to_ray;
|
||||
}
|
||||
|
@ -8071,7 +8090,8 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
|||
.face_normal = face_normal,
|
||||
};
|
||||
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
|
||||
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
|
||||
BKE_pbvh_raycast(
|
||||
ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original, srd.ss->stroke_id);
|
||||
|
||||
/* Cursor is not over the mesh, return default values. */
|
||||
if (!srd.hit) {
|
||||
|
@ -8198,7 +8218,8 @@ bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2])
|
|||
srd.face_normal = face_normal;
|
||||
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
|
||||
|
||||
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
|
||||
BKE_pbvh_raycast(
|
||||
ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original, srd.ss->stroke_id);
|
||||
if (srd.hit) {
|
||||
hit = true;
|
||||
copy_v3_v3(out, ray_normal);
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct {
|
|||
float edge_length;
|
||||
|
||||
struct IsectRayPrecalc isect_precalc;
|
||||
SculptSession *ss;
|
||||
} SculptDetailRaycastData;
|
||||
|
||||
static bool sculpt_and_constant_or_manual_detail_poll(bContext *C)
|
||||
|
@ -193,8 +194,13 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
|
|||
{
|
||||
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
|
||||
SculptDetailRaycastData *srd = data_v;
|
||||
if (BKE_pbvh_bmesh_node_raycast_detail(
|
||||
node, srd->ray_start, &srd->isect_precalc, &srd->depth, &srd->edge_length)) {
|
||||
|
||||
if (BKE_pbvh_bmesh_node_raycast_detail(srd->ss->pbvh,
|
||||
node,
|
||||
srd->ray_start,
|
||||
&srd->isect_precalc,
|
||||
&srd->depth,
|
||||
&srd->edge_length)) {
|
||||
srd->hit = true;
|
||||
*tmin = srd->depth;
|
||||
}
|
||||
|
@ -215,12 +221,14 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *region,
|
|||
|
||||
SculptDetailRaycastData srd;
|
||||
srd.hit = 0;
|
||||
srd.ss = ob->sculpt;
|
||||
|
||||
srd.ray_start = ray_start;
|
||||
srd.depth = depth;
|
||||
srd.edge_length = 0.0f;
|
||||
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
|
||||
|
||||
BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd, ray_start, ray_normal, false);
|
||||
BKE_pbvh_raycast(ob->sculpt->pbvh, sculpt_raycast_detail_cb, &srd, ray_start, ray_normal, false, srd.ss->stroke_id);
|
||||
|
||||
if (srd.hit && srd.edge_length > 0.0f) {
|
||||
/* Convert edge length to world space detail resolution. */
|
||||
|
|
|
@ -179,6 +179,7 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
|
|||
|
||||
SculptVertRef SCULPT_active_vertex_get(SculptSession *ss);
|
||||
const float *SCULPT_active_vertex_co_get(SculptSession *ss);
|
||||
const float *SCULPT_vertex_origco_get(SculptSession *ss, SculptVertRef vertex);
|
||||
void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3]);
|
||||
|
||||
/* Returns PBVH deformed vertices array if shape keys or deform modifiers are used, otherwise
|
||||
|
|
Loading…
Reference in New Issue