1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup bli
19 */
20
21 #include "MEM_guardedalloc.h"
22
23 #include "BLI_utildefines.h"
24
25 #include "BLI_bitmap.h"
26 #include "BLI_ghash.h"
27 #include "BLI_math.h"
28 #include "BLI_rand.h"
29 #include "BLI_task.h"
30
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33
34 #include "BKE_ccg.h"
35 #include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
36 #include "BKE_paint.h"
37 #include "BKE_pbvh.h"
38 #include "BKE_subdiv_ccg.h"
39
40 #include "PIL_time.h"
41
42 #include "GPU_buffers.h"
43
44 #include "bmesh.h"
45
46 #include "atomic_ops.h"
47
48 #include "pbvh_intern.h"
49
50 #include <limits.h>
51
52 #define LEAF_LIMIT 10000
53
54 //#define PERFCNTRS
55
56 #define STACK_FIXED_DEPTH 100
57
58 typedef struct PBVHStack {
59 PBVHNode *node;
60 bool revisiting;
61 } PBVHStack;
62
63 typedef struct PBVHIter {
64 PBVH *pbvh;
65 BKE_pbvh_SearchCallback scb;
66 void *search_data;
67
68 PBVHStack *stack;
69 int stacksize;
70
71 PBVHStack stackfixed[STACK_FIXED_DEPTH];
72 int stackspace;
73 } PBVHIter;
74
BB_reset(BB * bb)75 void BB_reset(BB *bb)
76 {
77 bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX;
78 bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
79 }
80
81 /* Expand the bounding box to include a new coordinate */
BB_expand(BB * bb,const float co[3])82 void BB_expand(BB *bb, const float co[3])
83 {
84 for (int i = 0; i < 3; i++) {
85 bb->bmin[i] = min_ff(bb->bmin[i], co[i]);
86 bb->bmax[i] = max_ff(bb->bmax[i], co[i]);
87 }
88 }
89
90 /* Expand the bounding box to include another bounding box */
BB_expand_with_bb(BB * bb,BB * bb2)91 void BB_expand_with_bb(BB *bb, BB *bb2)
92 {
93 for (int i = 0; i < 3; i++) {
94 bb->bmin[i] = min_ff(bb->bmin[i], bb2->bmin[i]);
95 bb->bmax[i] = max_ff(bb->bmax[i], bb2->bmax[i]);
96 }
97 }
98
99 /* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
BB_widest_axis(const BB * bb)100 int BB_widest_axis(const BB *bb)
101 {
102 float dim[3];
103
104 for (int i = 0; i < 3; i++) {
105 dim[i] = bb->bmax[i] - bb->bmin[i];
106 }
107
108 if (dim[0] > dim[1]) {
109 if (dim[0] > dim[2]) {
110 return 0;
111 }
112
113 return 2;
114 }
115
116 if (dim[1] > dim[2]) {
117 return 1;
118 }
119
120 return 2;
121 }
122
BBC_update_centroid(BBC * bbc)123 void BBC_update_centroid(BBC *bbc)
124 {
125 for (int i = 0; i < 3; i++) {
126 bbc->bcentroid[i] = (bbc->bmin[i] + bbc->bmax[i]) * 0.5f;
127 }
128 }
129
130 /* Not recursive */
update_node_vb(PBVH * pbvh,PBVHNode * node)131 static void update_node_vb(PBVH *pbvh, PBVHNode *node)
132 {
133 BB vb;
134
135 BB_reset(&vb);
136
137 if (node->flag & PBVH_Leaf) {
138 PBVHVertexIter vd;
139
140 BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
141 {
142 BB_expand(&vb, vd.co);
143 }
144 BKE_pbvh_vertex_iter_end;
145 }
146 else {
147 BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset].vb);
148 BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset + 1].vb);
149 }
150
151 node->vb = vb;
152 }
153
154 // void BKE_pbvh_node_BB_reset(PBVHNode *node)
155 //{
156 // BB_reset(&node->vb);
157 //}
158 //
159 // void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3])
160 //{
161 // BB_expand(&node->vb, co);
162 //}
163
face_materials_match(const MPoly * f1,const MPoly * f2)164 static bool face_materials_match(const MPoly *f1, const MPoly *f2)
165 {
166 return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) && (f1->mat_nr == f2->mat_nr));
167 }
168
grid_materials_match(const DMFlagMat * f1,const DMFlagMat * f2)169 static bool grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
170 {
171 return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) && (f1->mat_nr == f2->mat_nr));
172 }
173
174 /* Adapted from BLI_kdopbvh.c */
175 /* Returns the index of the first element on the right of the partition */
partition_indices(int * prim_indices,int lo,int hi,int axis,float mid,BBC * prim_bbc)176 static int partition_indices(int *prim_indices, int lo, int hi, int axis, float mid, BBC *prim_bbc)
177 {
178 int i = lo, j = hi;
179 for (;;) {
180 for (; prim_bbc[prim_indices[i]].bcentroid[axis] < mid; i++) {
181 /* pass */
182 }
183 for (; mid < prim_bbc[prim_indices[j]].bcentroid[axis]; j--) {
184 /* pass */
185 }
186
187 if (!(i < j)) {
188 return i;
189 }
190
191 SWAP(int, prim_indices[i], prim_indices[j]);
192 i++;
193 }
194 }
195
196 /* Returns the index of the first element on the right of the partition */
partition_indices_material(PBVH * pbvh,int lo,int hi)197 static int partition_indices_material(PBVH *pbvh, int lo, int hi)
198 {
199 const MPoly *mpoly = pbvh->mpoly;
200 const MLoopTri *looptri = pbvh->looptri;
201 const DMFlagMat *flagmats = pbvh->grid_flag_mats;
202 const int *indices = pbvh->prim_indices;
203 const void *first;
204 int i = lo, j = hi;
205
206 if (pbvh->looptri) {
207 first = &mpoly[looptri[pbvh->prim_indices[lo]].poly];
208 }
209 else {
210 first = &flagmats[pbvh->prim_indices[lo]];
211 }
212
213 for (;;) {
214 if (pbvh->looptri) {
215 for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) {
216 /* pass */
217 }
218 for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) {
219 /* pass */
220 }
221 }
222 else {
223 for (; grid_materials_match(first, &flagmats[indices[i]]); i++) {
224 /* pass */
225 }
226 for (; !grid_materials_match(first, &flagmats[indices[j]]); j--) {
227 /* pass */
228 }
229 }
230
231 if (!(i < j)) {
232 return i;
233 }
234
235 SWAP(int, pbvh->prim_indices[i], pbvh->prim_indices[j]);
236 i++;
237 }
238 }
239
pbvh_grow_nodes(PBVH * pbvh,int totnode)240 void pbvh_grow_nodes(PBVH *pbvh, int totnode)
241 {
242 if (UNLIKELY(totnode > pbvh->node_mem_count)) {
243 pbvh->node_mem_count = pbvh->node_mem_count + (pbvh->node_mem_count / 3);
244 if (pbvh->node_mem_count < totnode) {
245 pbvh->node_mem_count = totnode;
246 }
247 pbvh->nodes = MEM_recallocN(pbvh->nodes, sizeof(PBVHNode) * pbvh->node_mem_count);
248 }
249
250 pbvh->totnode = totnode;
251 }
252
253 /* Add a vertex to the map, with a positive value for unique vertices and
254 * a negative value for additional vertices */
map_insert_vert(PBVH * pbvh,GHash * map,unsigned int * face_verts,unsigned int * uniq_verts,int vertex)255 static int map_insert_vert(
256 PBVH *pbvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex)
257 {
258 void *key, **value_p;
259
260 key = POINTER_FROM_INT(vertex);
261 if (!BLI_ghash_ensure_p(map, key, &value_p)) {
262 int value_i;
263 if (BLI_BITMAP_TEST(pbvh->vert_bitmap, vertex) == 0) {
264 BLI_BITMAP_ENABLE(pbvh->vert_bitmap, vertex);
265 value_i = *uniq_verts;
266 (*uniq_verts)++;
267 }
268 else {
269 value_i = ~(*face_verts);
270 (*face_verts)++;
271 }
272 *value_p = POINTER_FROM_INT(value_i);
273 return value_i;
274 }
275
276 return POINTER_AS_INT(*value_p);
277 }
278
279 /* Find vertices used by the faces in this node and update the draw buffers */
build_mesh_leaf_node(PBVH * pbvh,PBVHNode * node)280 static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
281 {
282 bool has_visible = false;
283
284 node->uniq_verts = node->face_verts = 0;
285 const int totface = node->totprim;
286
287 /* reserve size is rough guess */
288 GHash *map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
289
290 int(*face_vert_indices)[3] = MEM_mallocN(sizeof(int[3]) * totface, "bvh node face vert indices");
291
292 node->face_vert_indices = (const int(*)[3])face_vert_indices;
293
294 if (pbvh->respect_hide == false) {
295 has_visible = true;
296 }
297
298 for (int i = 0; i < totface; i++) {
299 const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]];
300 for (int j = 0; j < 3; j++) {
301 face_vert_indices[i][j] = map_insert_vert(
302 pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->mloop[lt->tri[j]].v);
303 }
304
305 if (has_visible == false) {
306 if (!paint_is_face_hidden(lt, pbvh->verts, pbvh->mloop)) {
307 has_visible = true;
308 }
309 }
310 }
311
312 int *vert_indices = MEM_callocN(sizeof(int) * (node->uniq_verts + node->face_verts),
313 "bvh node vert indices");
314 node->vert_indices = vert_indices;
315
316 /* Build the vertex list, unique verts first */
317 GHashIterator gh_iter;
318 GHASH_ITER (gh_iter, map) {
319 void *value = BLI_ghashIterator_getValue(&gh_iter);
320 int ndx = POINTER_AS_INT(value);
321
322 if (ndx < 0) {
323 ndx = -ndx + node->uniq_verts - 1;
324 }
325
326 vert_indices[ndx] = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter));
327 }
328
329 for (int i = 0; i < totface; i++) {
330 const int sides = 3;
331
332 for (int j = 0; j < sides; j++) {
333 if (face_vert_indices[i][j] < 0) {
334 face_vert_indices[i][j] = -face_vert_indices[i][j] + node->uniq_verts - 1;
335 }
336 }
337 }
338
339 BKE_pbvh_node_mark_rebuild_draw(node);
340
341 BKE_pbvh_node_fully_hidden_set(node, !has_visible);
342
343 BLI_ghash_free(map, NULL, NULL);
344 }
345
update_vb(PBVH * pbvh,PBVHNode * node,BBC * prim_bbc,int offset,int count)346 static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int count)
347 {
348 BB_reset(&node->vb);
349 for (int i = offset + count - 1; i >= offset; i--) {
350 BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[pbvh->prim_indices[i]]));
351 }
352 node->orig_vb = node->vb;
353 }
354
355 /* Returns the number of visible quads in the nodes' grids. */
BKE_pbvh_count_grid_quads(BLI_bitmap ** grid_hidden,const int * grid_indices,int totgrid,int gridsize)356 int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
357 const int *grid_indices,
358 int totgrid,
359 int gridsize)
360 {
361 const int gridarea = (gridsize - 1) * (gridsize - 1);
362 int totquad = 0;
363
364 /* grid hidden layer is present, so have to check each grid for
365 * visibility */
366
367 for (int i = 0; i < totgrid; i++) {
368 const BLI_bitmap *gh = grid_hidden[grid_indices[i]];
369
370 if (gh) {
371 /* grid hidden are present, have to check each element */
372 for (int y = 0; y < gridsize - 1; y++) {
373 for (int x = 0; x < gridsize - 1; x++) {
374 if (!paint_is_grid_face_hidden(gh, gridsize, x, y)) {
375 totquad++;
376 }
377 }
378 }
379 }
380 else {
381 totquad += gridarea;
382 }
383 }
384
385 return totquad;
386 }
387
BKE_pbvh_sync_face_sets_to_grids(PBVH * pbvh)388 void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh)
389 {
390 const int gridsize = pbvh->gridkey.grid_size;
391 for (int i = 0; i < pbvh->totgrid; i++) {
392 BLI_bitmap *gh = pbvh->grid_hidden[i];
393 const int face_index = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, i);
394 if (!gh && pbvh->face_sets[face_index] < 0) {
395 gh = pbvh->grid_hidden[i] = BLI_BITMAP_NEW(pbvh->gridkey.grid_area,
396 "partialvis_update_grids");
397 }
398 if (gh) {
399 for (int y = 0; y < gridsize; y++) {
400 for (int x = 0; x < gridsize; x++) {
401 BLI_BITMAP_SET(gh, y * gridsize + x, pbvh->face_sets[face_index] < 0);
402 }
403 }
404 }
405 }
406 }
407
build_grid_leaf_node(PBVH * pbvh,PBVHNode * node)408 static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node)
409 {
410 int totquads = BKE_pbvh_count_grid_quads(
411 pbvh->grid_hidden, node->prim_indices, node->totprim, pbvh->gridkey.grid_size);
412 BKE_pbvh_node_fully_hidden_set(node, (totquads == 0));
413 BKE_pbvh_node_mark_rebuild_draw(node);
414 }
415
build_leaf(PBVH * pbvh,int node_index,BBC * prim_bbc,int offset,int count)416 static void build_leaf(PBVH *pbvh, int node_index, BBC *prim_bbc, int offset, int count)
417 {
418 pbvh->nodes[node_index].flag |= PBVH_Leaf;
419
420 pbvh->nodes[node_index].prim_indices = pbvh->prim_indices + offset;
421 pbvh->nodes[node_index].totprim = count;
422
423 /* Still need vb for searches */
424 update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
425
426 if (pbvh->looptri) {
427 build_mesh_leaf_node(pbvh, pbvh->nodes + node_index);
428 }
429 else {
430 build_grid_leaf_node(pbvh, pbvh->nodes + node_index);
431 }
432 }
433
434 /* Return zero if all primitives in the node can be drawn with the
435 * same material (including flat/smooth shading), non-zero otherwise */
leaf_needs_material_split(PBVH * pbvh,int offset,int count)436 static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
437 {
438 if (count <= 1) {
439 return false;
440 }
441
442 if (pbvh->looptri) {
443 const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
444 const MPoly *mp = &pbvh->mpoly[first->poly];
445
446 for (int i = offset + count - 1; i > offset; i--) {
447 int prim = pbvh->prim_indices[i];
448 const MPoly *mp_other = &pbvh->mpoly[pbvh->looptri[prim].poly];
449 if (!face_materials_match(mp, mp_other)) {
450 return true;
451 }
452 }
453 }
454 else {
455 const DMFlagMat *first = &pbvh->grid_flag_mats[pbvh->prim_indices[offset]];
456
457 for (int i = offset + count - 1; i > offset; i--) {
458 int prim = pbvh->prim_indices[i];
459 if (!grid_materials_match(first, &pbvh->grid_flag_mats[prim])) {
460 return true;
461 }
462 }
463 }
464
465 return false;
466 }
467
468 /* Recursively build a node in the tree
469 *
470 * vb is the voxel box around all of the primitives contained in
471 * this node.
472 *
473 * cb is the bounding box around all the centroids of the primitives
474 * contained in this node
475 *
476 * offset and start indicate a range in the array of primitive indices
477 */
478
build_sub(PBVH * pbvh,int node_index,BB * cb,BBC * prim_bbc,int offset,int count)479 static void build_sub(PBVH *pbvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count)
480 {
481 int end;
482 BB cb_backing;
483
484 /* Decide whether this is a leaf or not */
485 const bool below_leaf_limit = count <= pbvh->leaf_limit;
486 if (below_leaf_limit) {
487 if (!leaf_needs_material_split(pbvh, offset, count)) {
488 build_leaf(pbvh, node_index, prim_bbc, offset, count);
489 return;
490 }
491 }
492
493 /* Add two child nodes */
494 pbvh->nodes[node_index].children_offset = pbvh->totnode;
495 pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
496
497 /* Update parent node bounding box */
498 update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
499
500 if (!below_leaf_limit) {
501 /* Find axis with widest range of primitive centroids */
502 if (!cb) {
503 cb = &cb_backing;
504 BB_reset(cb);
505 for (int i = offset + count - 1; i >= offset; i--) {
506 BB_expand(cb, prim_bbc[pbvh->prim_indices[i]].bcentroid);
507 }
508 }
509 const int axis = BB_widest_axis(cb);
510
511 /* Partition primitives along that axis */
512 end = partition_indices(pbvh->prim_indices,
513 offset,
514 offset + count - 1,
515 axis,
516 (cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
517 prim_bbc);
518 }
519 else {
520 /* Partition primitives by material */
521 end = partition_indices_material(pbvh, offset, offset + count - 1);
522 }
523
524 /* Build children */
525 build_sub(pbvh, pbvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset);
526 build_sub(pbvh,
527 pbvh->nodes[node_index].children_offset + 1,
528 NULL,
529 prim_bbc,
530 end,
531 offset + count - end);
532 }
533
pbvh_build(PBVH * pbvh,BB * cb,BBC * prim_bbc,int totprim)534 static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
535 {
536 if (totprim != pbvh->totprim) {
537 pbvh->totprim = totprim;
538 if (pbvh->nodes) {
539 MEM_freeN(pbvh->nodes);
540 }
541 if (pbvh->prim_indices) {
542 MEM_freeN(pbvh->prim_indices);
543 }
544 pbvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices");
545 for (int i = 0; i < totprim; i++) {
546 pbvh->prim_indices[i] = i;
547 }
548 pbvh->totnode = 0;
549 if (pbvh->node_mem_count < 100) {
550 pbvh->node_mem_count = 100;
551 pbvh->nodes = MEM_callocN(sizeof(PBVHNode) * pbvh->node_mem_count, "bvh initial nodes");
552 }
553 }
554
555 pbvh->totnode = 1;
556 build_sub(pbvh, 0, cb, prim_bbc, 0, totprim);
557 }
558
559 /**
560 * Do a full rebuild with on Mesh data structure.
561 *
562 * \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH
563 * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
564 */
BKE_pbvh_build_mesh(PBVH * pbvh,const Mesh * mesh,const MPoly * mpoly,const MLoop * mloop,MVert * verts,int totvert,struct CustomData * vdata,struct CustomData * ldata,struct CustomData * pdata,const MLoopTri * looptri,int looptri_num)565 void BKE_pbvh_build_mesh(PBVH *pbvh,
566 const Mesh *mesh,
567 const MPoly *mpoly,
568 const MLoop *mloop,
569 MVert *verts,
570 int totvert,
571 struct CustomData *vdata,
572 struct CustomData *ldata,
573 struct CustomData *pdata,
574 const MLoopTri *looptri,
575 int looptri_num)
576 {
577 BBC *prim_bbc = NULL;
578 BB cb;
579
580 pbvh->mesh = mesh;
581 pbvh->type = PBVH_FACES;
582 pbvh->mpoly = mpoly;
583 pbvh->mloop = mloop;
584 pbvh->looptri = looptri;
585 pbvh->verts = verts;
586 pbvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
587 pbvh->totvert = totvert;
588 pbvh->leaf_limit = LEAF_LIMIT;
589 pbvh->vdata = vdata;
590 pbvh->ldata = ldata;
591 pbvh->pdata = pdata;
592
593 pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
594 pbvh->face_sets_color_default = mesh->face_sets_color_default;
595
596 BB_reset(&cb);
597
598 /* For each face, store the AABB and the AABB centroid */
599 prim_bbc = MEM_mallocN(sizeof(BBC) * looptri_num, "prim_bbc");
600
601 for (int i = 0; i < looptri_num; i++) {
602 const MLoopTri *lt = &looptri[i];
603 const int sides = 3;
604 BBC *bbc = prim_bbc + i;
605
606 BB_reset((BB *)bbc);
607
608 for (int j = 0; j < sides; j++) {
609 BB_expand((BB *)bbc, verts[pbvh->mloop[lt->tri[j]].v].co);
610 }
611
612 BBC_update_centroid(bbc);
613
614 BB_expand(&cb, bbc->bcentroid);
615 }
616
617 if (looptri_num) {
618 pbvh_build(pbvh, &cb, prim_bbc, looptri_num);
619 }
620
621 MEM_freeN(prim_bbc);
622 MEM_freeN(pbvh->vert_bitmap);
623 }
624
625 /* Do a full rebuild with on Grids data structure */
BKE_pbvh_build_grids(PBVH * pbvh,CCGElem ** grids,int totgrid,CCGKey * key,void ** gridfaces,DMFlagMat * flagmats,BLI_bitmap ** grid_hidden)626 void BKE_pbvh_build_grids(PBVH *pbvh,
627 CCGElem **grids,
628 int totgrid,
629 CCGKey *key,
630 void **gridfaces,
631 DMFlagMat *flagmats,
632 BLI_bitmap **grid_hidden)
633 {
634 const int gridsize = key->grid_size;
635
636 pbvh->type = PBVH_GRIDS;
637 pbvh->grids = grids;
638 pbvh->gridfaces = gridfaces;
639 pbvh->grid_flag_mats = flagmats;
640 pbvh->totgrid = totgrid;
641 pbvh->gridkey = *key;
642 pbvh->grid_hidden = grid_hidden;
643 pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), 1);
644
645 BB cb;
646 BB_reset(&cb);
647
648 /* For each grid, store the AABB and the AABB centroid */
649 BBC *prim_bbc = MEM_mallocN(sizeof(BBC) * totgrid, "prim_bbc");
650
651 for (int i = 0; i < totgrid; i++) {
652 CCGElem *grid = grids[i];
653 BBC *bbc = prim_bbc + i;
654
655 BB_reset((BB *)bbc);
656
657 for (int j = 0; j < gridsize * gridsize; j++) {
658 BB_expand((BB *)bbc, CCG_elem_offset_co(key, grid, j));
659 }
660
661 BBC_update_centroid(bbc);
662
663 BB_expand(&cb, bbc->bcentroid);
664 }
665
666 if (totgrid) {
667 pbvh_build(pbvh, &cb, prim_bbc, totgrid);
668 }
669
670 MEM_freeN(prim_bbc);
671 }
672
BKE_pbvh_new(void)673 PBVH *BKE_pbvh_new(void)
674 {
675 PBVH *pbvh = MEM_callocN(sizeof(PBVH), "pbvh");
676 pbvh->respect_hide = true;
677 return pbvh;
678 }
679
BKE_pbvh_free(PBVH * pbvh)680 void BKE_pbvh_free(PBVH *pbvh)
681 {
682 for (int i = 0; i < pbvh->totnode; i++) {
683 PBVHNode *node = &pbvh->nodes[i];
684
685 if (node->flag & PBVH_Leaf) {
686 if (node->draw_buffers) {
687 GPU_pbvh_buffers_free(node->draw_buffers);
688 }
689 if (node->vert_indices) {
690 MEM_freeN((void *)node->vert_indices);
691 }
692 if (node->face_vert_indices) {
693 MEM_freeN((void *)node->face_vert_indices);
694 }
695 if (node->bm_faces) {
696 BLI_gset_free(node->bm_faces, NULL);
697 }
698 if (node->bm_unique_verts) {
699 BLI_gset_free(node->bm_unique_verts, NULL);
700 }
701 if (node->bm_other_verts) {
702 BLI_gset_free(node->bm_other_verts, NULL);
703 }
704 }
705 }
706
707 if (pbvh->deformed) {
708 if (pbvh->verts) {
709 /* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
710
711 MEM_freeN((void *)pbvh->verts);
712 }
713 }
714
715 if (pbvh->looptri) {
716 MEM_freeN((void *)pbvh->looptri);
717 }
718
719 if (pbvh->nodes) {
720 MEM_freeN(pbvh->nodes);
721 }
722
723 if (pbvh->prim_indices) {
724 MEM_freeN(pbvh->prim_indices);
725 }
726
727 MEM_freeN(pbvh);
728 }
729
pbvh_iter_begin(PBVHIter * iter,PBVH * pbvh,BKE_pbvh_SearchCallback scb,void * search_data)730 static void pbvh_iter_begin(PBVHIter *iter,
731 PBVH *pbvh,
732 BKE_pbvh_SearchCallback scb,
733 void *search_data)
734 {
735 iter->pbvh = pbvh;
736 iter->scb = scb;
737 iter->search_data = search_data;
738
739 iter->stack = iter->stackfixed;
740 iter->stackspace = STACK_FIXED_DEPTH;
741
742 iter->stack[0].node = pbvh->nodes;
743 iter->stack[0].revisiting = false;
744 iter->stacksize = 1;
745 }
746
pbvh_iter_end(PBVHIter * iter)747 static void pbvh_iter_end(PBVHIter *iter)
748 {
749 if (iter->stackspace > STACK_FIXED_DEPTH) {
750 MEM_freeN(iter->stack);
751 }
752 }
753
pbvh_stack_push(PBVHIter * iter,PBVHNode * node,bool revisiting)754 static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, bool revisiting)
755 {
756 if (UNLIKELY(iter->stacksize == iter->stackspace)) {
757 iter->stackspace *= 2;
758 if (iter->stackspace != (STACK_FIXED_DEPTH * 2)) {
759 iter->stack = MEM_reallocN(iter->stack, sizeof(PBVHStack) * iter->stackspace);
760 }
761 else {
762 iter->stack = MEM_mallocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack");
763 memcpy(iter->stack, iter->stackfixed, sizeof(PBVHStack) * iter->stacksize);
764 }
765 }
766
767 iter->stack[iter->stacksize].node = node;
768 iter->stack[iter->stacksize].revisiting = revisiting;
769 iter->stacksize++;
770 }
771
pbvh_iter_next(PBVHIter * iter)772 static PBVHNode *pbvh_iter_next(PBVHIter *iter)
773 {
774 /* purpose here is to traverse tree, visiting child nodes before their
775 * parents, this order is necessary for e.g. computing bounding boxes */
776
777 while (iter->stacksize) {
778 /* pop node */
779 iter->stacksize--;
780 PBVHNode *node = iter->stack[iter->stacksize].node;
781
782 /* on a mesh with no faces this can happen
783 * can remove this check if we know meshes have at least 1 face */
784 if (node == NULL) {
785 return NULL;
786 }
787
788 bool revisiting = iter->stack[iter->stacksize].revisiting;
789
790 /* revisiting node already checked */
791 if (revisiting) {
792 return node;
793 }
794
795 if (iter->scb && !iter->scb(node, iter->search_data)) {
796 continue; /* don't traverse, outside of search zone */
797 }
798
799 if (node->flag & PBVH_Leaf) {
800 /* immediately hit leaf node */
801 return node;
802 }
803
804 /* come back later when children are done */
805 pbvh_stack_push(iter, node, true);
806
807 /* push two child nodes on the stack */
808 pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false);
809 pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false);
810 }
811
812 return NULL;
813 }
814
pbvh_iter_next_occluded(PBVHIter * iter)815 static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
816 {
817 while (iter->stacksize) {
818 /* pop node */
819 iter->stacksize--;
820 PBVHNode *node = iter->stack[iter->stacksize].node;
821
822 /* on a mesh with no faces this can happen
823 * can remove this check if we know meshes have at least 1 face */
824 if (node == NULL) {
825 return NULL;
826 }
827
828 if (iter->scb && !iter->scb(node, iter->search_data)) {
829 continue; /* don't traverse, outside of search zone */
830 }
831
832 if (node->flag & PBVH_Leaf) {
833 /* immediately hit leaf node */
834 return node;
835 }
836
837 pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false);
838 pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false);
839 }
840
841 return NULL;
842 }
843
BKE_pbvh_search_gather(PBVH * pbvh,BKE_pbvh_SearchCallback scb,void * search_data,PBVHNode *** r_array,int * r_tot)844 void BKE_pbvh_search_gather(
845 PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot)
846 {
847 PBVHIter iter;
848 PBVHNode **array = NULL, *node;
849 int tot = 0, space = 0;
850
851 pbvh_iter_begin(&iter, pbvh, scb, search_data);
852
853 while ((node = pbvh_iter_next(&iter))) {
854 if (node->flag & PBVH_Leaf) {
855 if (UNLIKELY(tot == space)) {
856 /* resize array if needed */
857 space = (tot == 0) ? 32 : space * 2;
858 array = MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__);
859 }
860
861 array[tot] = node;
862 tot++;
863 }
864 }
865
866 pbvh_iter_end(&iter);
867
868 if (tot == 0 && array) {
869 MEM_freeN(array);
870 array = NULL;
871 }
872
873 *r_array = array;
874 *r_tot = tot;
875 }
876
BKE_pbvh_search_callback(PBVH * pbvh,BKE_pbvh_SearchCallback scb,void * search_data,BKE_pbvh_HitCallback hcb,void * hit_data)877 void BKE_pbvh_search_callback(PBVH *pbvh,
878 BKE_pbvh_SearchCallback scb,
879 void *search_data,
880 BKE_pbvh_HitCallback hcb,
881 void *hit_data)
882 {
883 PBVHIter iter;
884 PBVHNode *node;
885
886 pbvh_iter_begin(&iter, pbvh, scb, search_data);
887
888 while ((node = pbvh_iter_next(&iter))) {
889 if (node->flag & PBVH_Leaf) {
890 hcb(node, hit_data);
891 }
892 }
893
894 pbvh_iter_end(&iter);
895 }
896
897 typedef struct node_tree {
898 PBVHNode *data;
899
900 struct node_tree *left;
901 struct node_tree *right;
902 } node_tree;
903
node_tree_insert(node_tree * tree,node_tree * new_node)904 static void node_tree_insert(node_tree *tree, node_tree *new_node)
905 {
906 if (new_node->data->tmin < tree->data->tmin) {
907 if (tree->left) {
908 node_tree_insert(tree->left, new_node);
909 }
910 else {
911 tree->left = new_node;
912 }
913 }
914 else {
915 if (tree->right) {
916 node_tree_insert(tree->right, new_node);
917 }
918 else {
919 tree->right = new_node;
920 }
921 }
922 }
923
traverse_tree(node_tree * tree,BKE_pbvh_HitOccludedCallback hcb,void * hit_data,float * tmin)924 static void traverse_tree(node_tree *tree,
925 BKE_pbvh_HitOccludedCallback hcb,
926 void *hit_data,
927 float *tmin)
928 {
929 if (tree->left) {
930 traverse_tree(tree->left, hcb, hit_data, tmin);
931 }
932
933 hcb(tree->data, hit_data, tmin);
934
935 if (tree->right) {
936 traverse_tree(tree->right, hcb, hit_data, tmin);
937 }
938 }
939
free_tree(node_tree * tree)940 static void free_tree(node_tree *tree)
941 {
942 if (tree->left) {
943 free_tree(tree->left);
944 tree->left = NULL;
945 }
946
947 if (tree->right) {
948 free_tree(tree->right);
949 tree->right = NULL;
950 }
951
952 free(tree);
953 }
954
BKE_pbvh_node_get_tmin(PBVHNode * node)955 float BKE_pbvh_node_get_tmin(PBVHNode *node)
956 {
957 return node->tmin;
958 }
959
BKE_pbvh_search_callback_occluded(PBVH * pbvh,BKE_pbvh_SearchCallback scb,void * search_data,BKE_pbvh_HitOccludedCallback hcb,void * hit_data)960 static void BKE_pbvh_search_callback_occluded(PBVH *pbvh,
961 BKE_pbvh_SearchCallback scb,
962 void *search_data,
963 BKE_pbvh_HitOccludedCallback hcb,
964 void *hit_data)
965 {
966 PBVHIter iter;
967 PBVHNode *node;
968 node_tree *tree = NULL;
969
970 pbvh_iter_begin(&iter, pbvh, scb, search_data);
971
972 while ((node = pbvh_iter_next_occluded(&iter))) {
973 if (node->flag & PBVH_Leaf) {
974 node_tree *new_node = malloc(sizeof(node_tree));
975
976 new_node->data = node;
977
978 new_node->left = NULL;
979 new_node->right = NULL;
980
981 if (tree) {
982 node_tree_insert(tree, new_node);
983 }
984 else {
985 tree = new_node;
986 }
987 }
988 }
989
990 pbvh_iter_end(&iter);
991
992 if (tree) {
993 float tmin = FLT_MAX;
994 traverse_tree(tree, hcb, hit_data, &tmin);
995 free_tree(tree);
996 }
997 }
998
update_search_cb(PBVHNode * node,void * data_v)999 static bool update_search_cb(PBVHNode *node, void *data_v)
1000 {
1001 int flag = POINTER_AS_INT(data_v);
1002
1003 if (node->flag & PBVH_Leaf) {
1004 return (node->flag & flag) != 0;
1005 }
1006
1007 return true;
1008 }
1009
1010 typedef struct PBVHUpdateData {
1011 PBVH *pbvh;
1012 PBVHNode **nodes;
1013 int totnode;
1014
1015 float (*vnors)[3];
1016 int flag;
1017 bool show_sculpt_face_sets;
1018 } PBVHUpdateData;
1019
pbvh_update_normals_accum_task_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1020 static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
1021 const int n,
1022 const TaskParallelTLS *__restrict UNUSED(tls))
1023 {
1024 PBVHUpdateData *data = userdata;
1025
1026 PBVH *pbvh = data->pbvh;
1027 PBVHNode *node = data->nodes[n];
1028 float(*vnors)[3] = data->vnors;
1029
1030 if ((node->flag & PBVH_UpdateNormals)) {
1031 unsigned int mpoly_prev = UINT_MAX;
1032 float fn[3];
1033
1034 const int *faces = node->prim_indices;
1035 const int totface = node->totprim;
1036
1037 for (int i = 0; i < totface; i++) {
1038 const MLoopTri *lt = &pbvh->looptri[faces[i]];
1039 const unsigned int vtri[3] = {
1040 pbvh->mloop[lt->tri[0]].v,
1041 pbvh->mloop[lt->tri[1]].v,
1042 pbvh->mloop[lt->tri[2]].v,
1043 };
1044 const int sides = 3;
1045
1046 /* Face normal and mask */
1047 if (lt->poly != mpoly_prev) {
1048 const MPoly *mp = &pbvh->mpoly[lt->poly];
1049 BKE_mesh_calc_poly_normal(mp, &pbvh->mloop[mp->loopstart], pbvh->verts, fn);
1050 mpoly_prev = lt->poly;
1051 }
1052
1053 for (int j = sides; j--;) {
1054 const int v = vtri[j];
1055
1056 if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
1057 /* Note: This avoids `lock, add_v3_v3, unlock`
1058 * and is five to ten times quicker than a spin-lock.
1059 * Not exact equivalent though, since atomicity is only ensured for one component
1060 * of the vector at a time, but here it shall not make any sensible difference. */
1061 for (int k = 3; k--;) {
1062 atomic_add_and_fetch_fl(&vnors[v][k], fn[k]);
1063 }
1064 }
1065 }
1066 }
1067 }
1068 }
1069
pbvh_update_normals_store_task_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1070 static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
1071 const int n,
1072 const TaskParallelTLS *__restrict UNUSED(tls))
1073 {
1074 PBVHUpdateData *data = userdata;
1075 PBVH *pbvh = data->pbvh;
1076 PBVHNode *node = data->nodes[n];
1077 float(*vnors)[3] = data->vnors;
1078
1079 if (node->flag & PBVH_UpdateNormals) {
1080 const int *verts = node->vert_indices;
1081 const int totvert = node->uniq_verts;
1082
1083 for (int i = 0; i < totvert; i++) {
1084 const int v = verts[i];
1085 MVert *mvert = &pbvh->verts[v];
1086
1087 /* No atomics necessary because we are iterating over uniq_verts only,
1088 * so we know only this thread will handle this vertex. */
1089 if (mvert->flag & ME_VERT_PBVH_UPDATE) {
1090 normalize_v3(vnors[v]);
1091 normal_float_to_short_v3(mvert->no, vnors[v]);
1092 mvert->flag &= ~ME_VERT_PBVH_UPDATE;
1093 }
1094 }
1095
1096 node->flag &= ~PBVH_UpdateNormals;
1097 }
1098 }
1099
pbvh_faces_update_normals(PBVH * pbvh,PBVHNode ** nodes,int totnode)1100 static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
1101 {
1102 /* could be per node to save some memory, but also means
1103 * we have to store for each vertex which node it is in */
1104 float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * pbvh->totvert, __func__);
1105
1106 /* subtle assumptions:
1107 * - We know that for all edited vertices, the nodes with faces
1108 * adjacent to these vertices have been marked with PBVH_UpdateNormals.
1109 * This is true because if the vertex is inside the brush radius, the
1110 * bounding box of its adjacent faces will be as well.
1111 * - However this is only true for the vertices that have actually been
1112 * edited, not for all vertices in the nodes marked for update, so we
1113 * can only update vertices marked with ME_VERT_PBVH_UPDATE.
1114 */
1115
1116 PBVHUpdateData data = {
1117 .pbvh = pbvh,
1118 .nodes = nodes,
1119 .vnors = vnors,
1120 };
1121
1122 TaskParallelSettings settings;
1123 BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1124
1125 BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings);
1126 BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings);
1127
1128 MEM_freeN(vnors);
1129 }
1130
pbvh_update_mask_redraw_task_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1131 static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
1132 const int n,
1133 const TaskParallelTLS *__restrict UNUSED(tls))
1134 {
1135
1136 PBVHUpdateData *data = userdata;
1137 PBVH *pbvh = data->pbvh;
1138 PBVHNode *node = data->nodes[n];
1139 if (node->flag & PBVH_UpdateMask) {
1140
1141 bool has_unmasked = false;
1142 bool has_masked = true;
1143 if (node->flag & PBVH_Leaf) {
1144 PBVHVertexIter vd;
1145
1146 BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
1147 {
1148 if (vd.mask && *vd.mask < 1.0f) {
1149 has_unmasked = true;
1150 }
1151 if (vd.mask && *vd.mask > 0.0f) {
1152 has_masked = false;
1153 }
1154 }
1155 BKE_pbvh_vertex_iter_end;
1156 }
1157 else {
1158 has_unmasked = true;
1159 has_masked = true;
1160 }
1161 BKE_pbvh_node_fully_masked_set(node, !has_unmasked);
1162 BKE_pbvh_node_fully_unmasked_set(node, has_masked);
1163
1164 node->flag &= ~PBVH_UpdateMask;
1165 }
1166 }
1167
pbvh_update_mask_redraw(PBVH * pbvh,PBVHNode ** nodes,int totnode,int flag)1168 static void pbvh_update_mask_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
1169 {
1170 PBVHUpdateData data = {
1171 .pbvh = pbvh,
1172 .nodes = nodes,
1173 .flag = flag,
1174 };
1175
1176 TaskParallelSettings settings;
1177 BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1178 BLI_task_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings);
1179 }
1180
pbvh_update_visibility_redraw_task_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1181 static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
1182 const int n,
1183 const TaskParallelTLS *__restrict UNUSED(tls))
1184 {
1185
1186 PBVHUpdateData *data = userdata;
1187 PBVH *pbvh = data->pbvh;
1188 PBVHNode *node = data->nodes[n];
1189 if (node->flag & PBVH_UpdateVisibility) {
1190 node->flag &= ~PBVH_UpdateVisibility;
1191 BKE_pbvh_node_fully_hidden_set(node, true);
1192 if (node->flag & PBVH_Leaf) {
1193 PBVHVertexIter vd;
1194 BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
1195 {
1196 if (vd.visible) {
1197 BKE_pbvh_node_fully_hidden_set(node, false);
1198 return;
1199 }
1200 }
1201 BKE_pbvh_vertex_iter_end;
1202 }
1203 }
1204 }
1205
pbvh_update_visibility_redraw(PBVH * pbvh,PBVHNode ** nodes,int totnode,int flag)1206 static void pbvh_update_visibility_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
1207 {
1208 PBVHUpdateData data = {
1209 .pbvh = pbvh,
1210 .nodes = nodes,
1211 .flag = flag,
1212 };
1213
1214 TaskParallelSettings settings;
1215 BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1216 BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings);
1217 }
1218
pbvh_update_BB_redraw_task_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1219 static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
1220 const int n,
1221 const TaskParallelTLS *__restrict UNUSED(tls))
1222 {
1223 PBVHUpdateData *data = userdata;
1224 PBVH *pbvh = data->pbvh;
1225 PBVHNode *node = data->nodes[n];
1226 const int flag = data->flag;
1227
1228 if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) {
1229 /* don't clear flag yet, leave it for flushing later */
1230 /* Note that bvh usage is read-only here, so no need to thread-protect it. */
1231 update_node_vb(pbvh, node);
1232 }
1233
1234 if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) {
1235 node->orig_vb = node->vb;
1236 }
1237
1238 if ((flag & PBVH_UpdateRedraw) && (node->flag & PBVH_UpdateRedraw)) {
1239 node->flag &= ~PBVH_UpdateRedraw;
1240 }
1241 }
1242
pbvh_update_BB_redraw(PBVH * pbvh,PBVHNode ** nodes,int totnode,int flag)1243 void pbvh_update_BB_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
1244 {
1245 /* update BB, redraw flag */
1246 PBVHUpdateData data = {
1247 .pbvh = pbvh,
1248 .nodes = nodes,
1249 .flag = flag,
1250 };
1251
1252 TaskParallelSettings settings;
1253 BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1254 BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
1255 }
1256
pbvh_get_buffers_update_flags(PBVH * UNUSED (pbvh))1257 static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh))
1258 {
1259 int update_flags = GPU_PBVH_BUFFERS_SHOW_VCOL | GPU_PBVH_BUFFERS_SHOW_MASK |
1260 GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS;
1261 return update_flags;
1262 }
1263
pbvh_update_draw_buffer_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1264 static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
1265 const int n,
1266 const TaskParallelTLS *__restrict UNUSED(tls))
1267 {
1268 /* Create and update draw buffers. The functions called here must not
1269 * do any OpenGL calls. Flags are not cleared immediately, that happens
1270 * after GPU_pbvh_buffer_flush() which does the final OpenGL calls. */
1271 PBVHUpdateData *data = userdata;
1272 PBVH *pbvh = data->pbvh;
1273 PBVHNode *node = data->nodes[n];
1274
1275 if (node->flag & PBVH_RebuildDrawBuffers) {
1276 switch (pbvh->type) {
1277 case PBVH_GRIDS:
1278 node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, pbvh->grid_hidden);
1279 break;
1280 case PBVH_FACES:
1281 node->draw_buffers = GPU_pbvh_mesh_buffers_build(
1282 pbvh->mpoly,
1283 pbvh->mloop,
1284 pbvh->looptri,
1285 pbvh->verts,
1286 node->prim_indices,
1287 CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
1288 node->totprim,
1289 pbvh->mesh);
1290 break;
1291 case PBVH_BMESH:
1292 node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags &
1293 PBVH_DYNTOPO_SMOOTH_SHADING);
1294 break;
1295 }
1296 }
1297
1298 if (node->flag & PBVH_UpdateDrawBuffers) {
1299 const int update_flags = pbvh_get_buffers_update_flags(pbvh);
1300 switch (pbvh->type) {
1301 case PBVH_GRIDS:
1302 GPU_pbvh_grid_buffers_update(node->draw_buffers,
1303 pbvh->subdiv_ccg,
1304 pbvh->grids,
1305 pbvh->grid_flag_mats,
1306 node->prim_indices,
1307 node->totprim,
1308 pbvh->face_sets,
1309 pbvh->face_sets_color_seed,
1310 pbvh->face_sets_color_default,
1311 &pbvh->gridkey,
1312 update_flags);
1313 break;
1314 case PBVH_FACES:
1315 GPU_pbvh_mesh_buffers_update(node->draw_buffers,
1316 pbvh->verts,
1317 CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK),
1318 CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL),
1319 CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
1320 pbvh->face_sets_color_seed,
1321 pbvh->face_sets_color_default,
1322 CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR),
1323 update_flags);
1324 break;
1325 case PBVH_BMESH:
1326 GPU_pbvh_bmesh_buffers_update(node->draw_buffers,
1327 pbvh->bm,
1328 node->bm_faces,
1329 node->bm_unique_verts,
1330 node->bm_other_verts,
1331 update_flags);
1332 break;
1333 }
1334 }
1335 }
1336
pbvh_update_draw_buffers(PBVH * pbvh,PBVHNode ** nodes,int totnode,int update_flag)1337 static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
1338 {
1339 if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
1340 /* Free buffers uses OpenGL, so not in parallel. */
1341 for (int n = 0; n < totnode; n++) {
1342 PBVHNode *node = nodes[n];
1343 if (node->flag & PBVH_RebuildDrawBuffers) {
1344 GPU_pbvh_buffers_free(node->draw_buffers);
1345 node->draw_buffers = NULL;
1346 }
1347 else if ((node->flag & PBVH_UpdateDrawBuffers) && node->draw_buffers) {
1348 if (pbvh->type == PBVH_GRIDS) {
1349 GPU_pbvh_grid_buffers_update_free(
1350 node->draw_buffers, pbvh->grid_flag_mats, node->prim_indices);
1351 }
1352 else if (pbvh->type == PBVH_BMESH) {
1353 GPU_pbvh_bmesh_buffers_update_free(node->draw_buffers);
1354 }
1355 }
1356 }
1357 }
1358
1359 /* Parallel creation and update of draw buffers. */
1360 PBVHUpdateData data = {
1361 .pbvh = pbvh,
1362 .nodes = nodes,
1363 };
1364
1365 TaskParallelSettings settings;
1366 BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1367 BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
1368 }
1369
pbvh_flush_bb(PBVH * pbvh,PBVHNode * node,int flag)1370 static int pbvh_flush_bb(PBVH *pbvh, PBVHNode *node, int flag)
1371 {
1372 int update = 0;
1373
1374 /* difficult to multithread well, we just do single threaded recursive */
1375 if (node->flag & PBVH_Leaf) {
1376 if (flag & PBVH_UpdateBB) {
1377 update |= (node->flag & PBVH_UpdateBB);
1378 node->flag &= ~PBVH_UpdateBB;
1379 }
1380
1381 if (flag & PBVH_UpdateOriginalBB) {
1382 update |= (node->flag & PBVH_UpdateOriginalBB);
1383 node->flag &= ~PBVH_UpdateOriginalBB;
1384 }
1385
1386 return update;
1387 }
1388
1389 update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset, flag);
1390 update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset + 1, flag);
1391
1392 if (update & PBVH_UpdateBB) {
1393 update_node_vb(pbvh, node);
1394 }
1395 if (update & PBVH_UpdateOriginalBB) {
1396 node->orig_vb = node->vb;
1397 }
1398
1399 return update;
1400 }
1401
BKE_pbvh_update_bounds(PBVH * pbvh,int flag)1402 void BKE_pbvh_update_bounds(PBVH *pbvh, int flag)
1403 {
1404 if (!pbvh->nodes) {
1405 return;
1406 }
1407
1408 PBVHNode **nodes;
1409 int totnode;
1410
1411 BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
1412
1413 if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw)) {
1414 pbvh_update_BB_redraw(pbvh, nodes, totnode, flag);
1415 }
1416
1417 if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB)) {
1418 pbvh_flush_bb(pbvh, pbvh->nodes, flag);
1419 }
1420
1421 MEM_SAFE_FREE(nodes);
1422 }
1423
BKE_pbvh_update_vertex_data(PBVH * pbvh,int flag)1424 void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
1425 {
1426 if (!pbvh->nodes) {
1427 return;
1428 }
1429
1430 PBVHNode **nodes;
1431 int totnode;
1432
1433 BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
1434
1435 if (flag & (PBVH_UpdateMask)) {
1436 pbvh_update_mask_redraw(pbvh, nodes, totnode, flag);
1437 }
1438
1439 if (flag & (PBVH_UpdateColor)) {
1440 /* Do nothing */
1441 }
1442
1443 if (flag & (PBVH_UpdateVisibility)) {
1444 pbvh_update_visibility_redraw(pbvh, nodes, totnode, flag);
1445 }
1446
1447 if (nodes) {
1448 MEM_freeN(nodes);
1449 }
1450 }
1451
pbvh_faces_node_visibility_update(PBVH * pbvh,PBVHNode * node)1452 static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
1453 {
1454 MVert *mvert;
1455 const int *vert_indices;
1456 int totvert, i;
1457 BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
1458 BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
1459
1460 for (i = 0; i < totvert; i++) {
1461 MVert *v = &mvert[vert_indices[i]];
1462 if (!(v->flag & ME_HIDE)) {
1463 BKE_pbvh_node_fully_hidden_set(node, false);
1464 return;
1465 }
1466 }
1467
1468 BKE_pbvh_node_fully_hidden_set(node, true);
1469 }
1470
pbvh_grids_node_visibility_update(PBVH * pbvh,PBVHNode * node)1471 static void pbvh_grids_node_visibility_update(PBVH *pbvh, PBVHNode *node)
1472 {
1473 CCGElem **grids;
1474 BLI_bitmap **grid_hidden;
1475 int *grid_indices, totgrid, i;
1476
1477 BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
1478 grid_hidden = BKE_pbvh_grid_hidden(pbvh);
1479 CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
1480
1481 for (i = 0; i < totgrid; i++) {
1482 int g = grid_indices[i], x, y;
1483 BLI_bitmap *gh = grid_hidden[g];
1484
1485 if (!gh) {
1486 BKE_pbvh_node_fully_hidden_set(node, false);
1487 return;
1488 }
1489
1490 for (y = 0; y < key.grid_size; y++) {
1491 for (x = 0; x < key.grid_size; x++) {
1492 if (!BLI_BITMAP_TEST(gh, y * key.grid_size + x)) {
1493 BKE_pbvh_node_fully_hidden_set(node, false);
1494 return;
1495 }
1496 }
1497 }
1498 }
1499 BKE_pbvh_node_fully_hidden_set(node, true);
1500 }
1501
pbvh_bmesh_node_visibility_update(PBVHNode * node)1502 static void pbvh_bmesh_node_visibility_update(PBVHNode *node)
1503 {
1504 GSet *unique, *other;
1505
1506 unique = BKE_pbvh_bmesh_node_unique_verts(node);
1507 other = BKE_pbvh_bmesh_node_other_verts(node);
1508
1509 GSetIterator gs_iter;
1510
1511 GSET_ITER (gs_iter, unique) {
1512 BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
1513 if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
1514 BKE_pbvh_node_fully_hidden_set(node, false);
1515 return;
1516 }
1517 }
1518
1519 GSET_ITER (gs_iter, other) {
1520 BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
1521 if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
1522 BKE_pbvh_node_fully_hidden_set(node, false);
1523 return;
1524 }
1525 }
1526
1527 BKE_pbvh_node_fully_hidden_set(node, true);
1528 }
1529
pbvh_update_visibility_task_cb(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))1530 static void pbvh_update_visibility_task_cb(void *__restrict userdata,
1531 const int n,
1532 const TaskParallelTLS *__restrict UNUSED(tls))
1533 {
1534
1535 PBVHUpdateData *data = userdata;
1536 PBVH *pbvh = data->pbvh;
1537 PBVHNode *node = data->nodes[n];
1538 if (node->flag & PBVH_UpdateVisibility) {
1539 switch (BKE_pbvh_type(pbvh)) {
1540 case PBVH_FACES:
1541 pbvh_faces_node_visibility_update(pbvh, node);
1542 break;
1543 case PBVH_GRIDS:
1544 pbvh_grids_node_visibility_update(pbvh, node);
1545 break;
1546 case PBVH_BMESH:
1547 pbvh_bmesh_node_visibility_update(node);
1548 break;
1549 }
1550 node->flag &= ~PBVH_UpdateVisibility;
1551 }
1552 }
1553
pbvh_update_visibility(PBVH * pbvh,PBVHNode ** nodes,int totnode)1554 static void pbvh_update_visibility(PBVH *pbvh, PBVHNode **nodes, int totnode)
1555 {
1556 PBVHUpdateData data = {
1557 .pbvh = pbvh,
1558 .nodes = nodes,
1559 };
1560
1561 TaskParallelSettings settings;
1562 BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1563 BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings);
1564 }
1565
BKE_pbvh_update_visibility(PBVH * pbvh)1566 void BKE_pbvh_update_visibility(PBVH *pbvh)
1567 {
1568 if (!pbvh->nodes) {
1569 return;
1570 }
1571
1572 PBVHNode **nodes;
1573 int totnode;
1574
1575 BKE_pbvh_search_gather(
1576 pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
1577 pbvh_update_visibility(pbvh, nodes, totnode);
1578
1579 if (nodes) {
1580 MEM_freeN(nodes);
1581 }
1582 }
1583
BKE_pbvh_redraw_BB(PBVH * pbvh,float bb_min[3],float bb_max[3])1584 void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
1585 {
1586 PBVHIter iter;
1587 PBVHNode *node;
1588 BB bb;
1589
1590 BB_reset(&bb);
1591
1592 pbvh_iter_begin(&iter, pbvh, NULL, NULL);
1593
1594 while ((node = pbvh_iter_next(&iter))) {
1595 if (node->flag & PBVH_UpdateRedraw) {
1596 BB_expand_with_bb(&bb, &node->vb);
1597 }
1598 }
1599
1600 pbvh_iter_end(&iter);
1601
1602 copy_v3_v3(bb_min, bb.bmin);
1603 copy_v3_v3(bb_max, bb.bmax);
1604 }
1605
BKE_pbvh_get_grid_updates(PBVH * pbvh,bool clear,void *** r_gridfaces,int * r_totface)1606 void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface)
1607 {
1608 GSet *face_set = BLI_gset_ptr_new(__func__);
1609 PBVHNode *node;
1610 PBVHIter iter;
1611
1612 pbvh_iter_begin(&iter, pbvh, NULL, NULL);
1613
1614 while ((node = pbvh_iter_next(&iter))) {
1615 if (node->flag & PBVH_UpdateNormals) {
1616 for (uint i = 0; i < node->totprim; i++) {
1617 void *face = pbvh->gridfaces[node->prim_indices[i]];
1618 BLI_gset_add(face_set, face);
1619 }
1620
1621 if (clear) {
1622 node->flag &= ~PBVH_UpdateNormals;
1623 }
1624 }
1625 }
1626
1627 pbvh_iter_end(&iter);
1628
1629 const int tot = BLI_gset_len(face_set);
1630 if (tot == 0) {
1631 *r_totface = 0;
1632 *r_gridfaces = NULL;
1633 BLI_gset_free(face_set, NULL);
1634 return;
1635 }
1636
1637 void **faces = MEM_mallocN(sizeof(*faces) * tot, "PBVH Grid Faces");
1638
1639 GSetIterator gs_iter;
1640 int i;
1641 GSET_ITER_INDEX (gs_iter, face_set, i) {
1642 faces[i] = BLI_gsetIterator_getKey(&gs_iter);
1643 }
1644
1645 BLI_gset_free(face_set, NULL);
1646
1647 *r_totface = tot;
1648 *r_gridfaces = faces;
1649 }
1650
1651 /***************************** PBVH Access ***********************************/
1652
BKE_pbvh_type(const PBVH * pbvh)1653 PBVHType BKE_pbvh_type(const PBVH *pbvh)
1654 {
1655 return pbvh->type;
1656 }
1657
BKE_pbvh_has_faces(const PBVH * pbvh)1658 bool BKE_pbvh_has_faces(const PBVH *pbvh)
1659 {
1660 if (pbvh->type == PBVH_BMESH) {
1661 return (pbvh->bm->totface != 0);
1662 }
1663
1664 return (pbvh->totprim != 0);
1665 }
1666
BKE_pbvh_bounding_box(const PBVH * pbvh,float min[3],float max[3])1667 void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3])
1668 {
1669 if (pbvh->totnode) {
1670 const BB *bb = &pbvh->nodes[0].vb;
1671 copy_v3_v3(min, bb->bmin);
1672 copy_v3_v3(max, bb->bmax);
1673 }
1674 else {
1675 zero_v3(min);
1676 zero_v3(max);
1677 }
1678 }
1679
BKE_pbvh_grid_hidden(const PBVH * pbvh)1680 BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *pbvh)
1681 {
1682 BLI_assert(pbvh->type == PBVH_GRIDS);
1683 return pbvh->grid_hidden;
1684 }
1685
BKE_pbvh_get_grid_key(const PBVH * pbvh)1686 const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh)
1687 {
1688 BLI_assert(pbvh->type == PBVH_GRIDS);
1689 return &pbvh->gridkey;
1690 }
1691
BKE_pbvh_get_grids(const PBVH * pbvh)1692 struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh)
1693 {
1694 BLI_assert(pbvh->type == PBVH_GRIDS);
1695 return pbvh->grids;
1696 }
1697
BKE_pbvh_get_grid_visibility(const PBVH * pbvh)1698 BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
1699 {
1700 BLI_assert(pbvh->type == PBVH_GRIDS);
1701 return pbvh->grid_hidden;
1702 }
1703
BKE_pbvh_get_grid_num_vertices(const PBVH * pbvh)1704 int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh)
1705 {
1706 BLI_assert(pbvh->type == PBVH_GRIDS);
1707 return pbvh->totgrid * pbvh->gridkey.grid_area;
1708 }
1709
BKE_pbvh_get_bmesh(PBVH * pbvh)1710 BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh)
1711 {
1712 BLI_assert(pbvh->type == PBVH_BMESH);
1713 return pbvh->bm;
1714 }
1715
1716 /***************************** Node Access ***********************************/
1717
BKE_pbvh_node_mark_update(PBVHNode * node)1718 void BKE_pbvh_node_mark_update(PBVHNode *node)
1719 {
1720 node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB |
1721 PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
1722 }
1723
BKE_pbvh_node_mark_update_mask(PBVHNode * node)1724 void BKE_pbvh_node_mark_update_mask(PBVHNode *node)
1725 {
1726 node->flag |= PBVH_UpdateMask | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
1727 }
1728
BKE_pbvh_node_mark_update_color(PBVHNode * node)1729 void BKE_pbvh_node_mark_update_color(PBVHNode *node)
1730 {
1731 node->flag |= PBVH_UpdateColor | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
1732 }
1733
BKE_pbvh_node_mark_update_visibility(PBVHNode * node)1734 void BKE_pbvh_node_mark_update_visibility(PBVHNode *node)
1735 {
1736 node->flag |= PBVH_UpdateVisibility | PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers |
1737 PBVH_UpdateRedraw;
1738 }
1739
BKE_pbvh_node_mark_rebuild_draw(PBVHNode * node)1740 void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node)
1741 {
1742 node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
1743 }
1744
BKE_pbvh_node_mark_redraw(PBVHNode * node)1745 void BKE_pbvh_node_mark_redraw(PBVHNode *node)
1746 {
1747 node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
1748 }
1749
BKE_pbvh_node_mark_normals_update(PBVHNode * node)1750 void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
1751 {
1752 node->flag |= PBVH_UpdateNormals;
1753 }
1754
BKE_pbvh_node_fully_hidden_set(PBVHNode * node,int fully_hidden)1755 void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
1756 {
1757 BLI_assert(node->flag & PBVH_Leaf);
1758
1759 if (fully_hidden) {
1760 node->flag |= PBVH_FullyHidden;
1761 }
1762 else {
1763 node->flag &= ~PBVH_FullyHidden;
1764 }
1765 }
1766
BKE_pbvh_node_fully_hidden_get(PBVHNode * node)1767 bool BKE_pbvh_node_fully_hidden_get(PBVHNode *node)
1768 {
1769 return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyHidden);
1770 }
1771
BKE_pbvh_node_fully_masked_set(PBVHNode * node,int fully_masked)1772 void BKE_pbvh_node_fully_masked_set(PBVHNode *node, int fully_masked)
1773 {
1774 BLI_assert(node->flag & PBVH_Leaf);
1775
1776 if (fully_masked) {
1777 node->flag |= PBVH_FullyMasked;
1778 }
1779 else {
1780 node->flag &= ~PBVH_FullyMasked;
1781 }
1782 }
1783
BKE_pbvh_node_fully_masked_get(PBVHNode * node)1784 bool BKE_pbvh_node_fully_masked_get(PBVHNode *node)
1785 {
1786 return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyMasked);
1787 }
1788
BKE_pbvh_node_fully_unmasked_set(PBVHNode * node,int fully_masked)1789 void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked)
1790 {
1791 BLI_assert(node->flag & PBVH_Leaf);
1792
1793 if (fully_masked) {
1794 node->flag |= PBVH_FullyUnmasked;
1795 }
1796 else {
1797 node->flag &= ~PBVH_FullyUnmasked;
1798 }
1799 }
1800
BKE_pbvh_node_fully_unmasked_get(PBVHNode * node)1801 bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node)
1802 {
1803 return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked);
1804 }
1805
BKE_pbvh_node_get_verts(PBVH * pbvh,PBVHNode * node,const int ** r_vert_indices,MVert ** r_verts)1806 void BKE_pbvh_node_get_verts(PBVH *pbvh,
1807 PBVHNode *node,
1808 const int **r_vert_indices,
1809 MVert **r_verts)
1810 {
1811 if (r_vert_indices) {
1812 *r_vert_indices = node->vert_indices;
1813 }
1814
1815 if (r_verts) {
1816 *r_verts = pbvh->verts;
1817 }
1818 }
1819
BKE_pbvh_node_num_verts(PBVH * pbvh,PBVHNode * node,int * r_uniquevert,int * r_totvert)1820 void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert)
1821 {
1822 int tot;
1823
1824 switch (pbvh->type) {
1825 case PBVH_GRIDS:
1826 tot = node->totprim * pbvh->gridkey.grid_area;
1827 if (r_totvert) {
1828 *r_totvert = tot;
1829 }
1830 if (r_uniquevert) {
1831 *r_uniquevert = tot;
1832 }
1833 break;
1834 case PBVH_FACES:
1835 if (r_totvert) {
1836 *r_totvert = node->uniq_verts + node->face_verts;
1837 }
1838 if (r_uniquevert) {
1839 *r_uniquevert = node->uniq_verts;
1840 }
1841 break;
1842 case PBVH_BMESH:
1843 tot = BLI_gset_len(node->bm_unique_verts);
1844 if (r_totvert) {
1845 *r_totvert = tot + BLI_gset_len(node->bm_other_verts);
1846 }
1847 if (r_uniquevert) {
1848 *r_uniquevert = tot;
1849 }
1850 break;
1851 }
1852 }
1853
BKE_pbvh_node_get_grids(PBVH * pbvh,PBVHNode * node,int ** r_grid_indices,int * r_totgrid,int * r_maxgrid,int * r_gridsize,CCGElem *** r_griddata)1854 void BKE_pbvh_node_get_grids(PBVH *pbvh,
1855 PBVHNode *node,
1856 int **r_grid_indices,
1857 int *r_totgrid,
1858 int *r_maxgrid,
1859 int *r_gridsize,
1860 CCGElem ***r_griddata)
1861 {
1862 switch (pbvh->type) {
1863 case PBVH_GRIDS:
1864 if (r_grid_indices) {
1865 *r_grid_indices = node->prim_indices;
1866 }
1867 if (r_totgrid) {
1868 *r_totgrid = node->totprim;
1869 }
1870 if (r_maxgrid) {
1871 *r_maxgrid = pbvh->totgrid;
1872 }
1873 if (r_gridsize) {
1874 *r_gridsize = pbvh->gridkey.grid_size;
1875 }
1876 if (r_griddata) {
1877 *r_griddata = pbvh->grids;
1878 }
1879 break;
1880 case PBVH_FACES:
1881 case PBVH_BMESH:
1882 if (r_grid_indices) {
1883 *r_grid_indices = NULL;
1884 }
1885 if (r_totgrid) {
1886 *r_totgrid = 0;
1887 }
1888 if (r_maxgrid) {
1889 *r_maxgrid = 0;
1890 }
1891 if (r_gridsize) {
1892 *r_gridsize = 0;
1893 }
1894 if (r_griddata) {
1895 *r_griddata = NULL;
1896 }
1897 break;
1898 }
1899 }
1900
BKE_pbvh_node_get_BB(PBVHNode * node,float bb_min[3],float bb_max[3])1901 void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
1902 {
1903 copy_v3_v3(bb_min, node->vb.bmin);
1904 copy_v3_v3(bb_max, node->vb.bmax);
1905 }
1906
BKE_pbvh_node_get_original_BB(PBVHNode * node,float bb_min[3],float bb_max[3])1907 void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
1908 {
1909 copy_v3_v3(bb_min, node->orig_vb.bmin);
1910 copy_v3_v3(bb_max, node->orig_vb.bmax);
1911 }
1912
BKE_pbvh_node_get_proxies(PBVHNode * node,PBVHProxyNode ** proxies,int * proxy_count)1913 void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
1914 {
1915 if (node->proxy_count > 0) {
1916 if (proxies) {
1917 *proxies = node->proxies;
1918 }
1919 if (proxy_count) {
1920 *proxy_count = node->proxy_count;
1921 }
1922 }
1923 else {
1924 if (proxies) {
1925 *proxies = NULL;
1926 }
1927 if (proxy_count) {
1928 *proxy_count = 0;
1929 }
1930 }
1931 }
1932
BKE_pbvh_node_get_bm_orco_data(PBVHNode * node,int (** r_orco_tris)[3],int * r_orco_tris_num,float (** r_orco_coords)[3])1933 void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
1934 int (**r_orco_tris)[3],
1935 int *r_orco_tris_num,
1936 float (**r_orco_coords)[3])
1937 {
1938 *r_orco_tris = node->bm_ortri;
1939 *r_orco_tris_num = node->bm_tot_ortri;
1940 *r_orco_coords = node->bm_orco;
1941 }
1942
1943 /**
1944 * \note doing a full search on all vertices here seems expensive,
1945 * however this is important to avoid having to recalculate bound-box & sync the buffers to the
1946 * GPU (which is far more expensive!) See: T47232.
1947 */
BKE_pbvh_node_vert_update_check_any(PBVH * pbvh,PBVHNode * node)1948 bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node)
1949 {
1950 BLI_assert(pbvh->type == PBVH_FACES);
1951 const int *verts = node->vert_indices;
1952 const int totvert = node->uniq_verts + node->face_verts;
1953
1954 for (int i = 0; i < totvert; i++) {
1955 const int v = verts[i];
1956 const MVert *mvert = &pbvh->verts[v];
1957
1958 if (mvert->flag & ME_VERT_PBVH_UPDATE) {
1959 return true;
1960 }
1961 }
1962
1963 return false;
1964 }
1965
1966 /********************************* Raycast ***********************************/
1967
1968 typedef struct {
1969 struct IsectRayAABB_Precalc ray;
1970 bool original;
1971 } RaycastData;
1972
ray_aabb_intersect(PBVHNode * node,void * data_v)1973 static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
1974 {
1975 RaycastData *rcd = data_v;
1976 const float *bb_min, *bb_max;
1977
1978 if (rcd->original) {
1979 /* BKE_pbvh_node_get_original_BB */
1980 bb_min = node->orig_vb.bmin;
1981 bb_max = node->orig_vb.bmax;
1982 }
1983 else {
1984 /* BKE_pbvh_node_get_BB */
1985 bb_min = node->vb.bmin;
1986 bb_max = node->vb.bmax;
1987 }
1988
1989 return isect_ray_aabb_v3(&rcd->ray, bb_min, bb_max, &node->tmin);
1990 }
1991
BKE_pbvh_raycast(PBVH * pbvh,BKE_pbvh_HitOccludedCallback cb,void * data,const float ray_start[3],const float ray_normal[3],bool original)1992 void BKE_pbvh_raycast(PBVH *pbvh,
1993 BKE_pbvh_HitOccludedCallback cb,
1994 void *data,
1995 const float ray_start[3],
1996 const float ray_normal[3],
1997 bool original)
1998 {
1999 RaycastData rcd;
2000
2001 isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal);
2002 rcd.original = original;
2003
2004 BKE_pbvh_search_callback_occluded(pbvh, ray_aabb_intersect, &rcd, cb, data);
2005 }
2006
ray_face_intersection_quad(const float ray_start[3],struct IsectRayPrecalc * isect_precalc,const float t0[3],const float t1[3],const float t2[3],const float t3[3],float * depth)2007 bool ray_face_intersection_quad(const float ray_start[3],
2008 struct IsectRayPrecalc *isect_precalc,
2009 const float t0[3],
2010 const float t1[3],
2011 const float t2[3],
2012 const float t3[3],
2013 float *depth)
2014 {
2015 float depth_test;
2016
2017 if ((isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t1, t2, &depth_test, NULL) &&
2018 (depth_test < *depth)) ||
2019 (isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t2, t3, &depth_test, NULL) &&
2020 (depth_test < *depth))) {
2021 *depth = depth_test;
2022 return true;
2023 }
2024
2025 return false;
2026 }
2027
ray_face_intersection_tri(const float ray_start[3],struct IsectRayPrecalc * isect_precalc,const float t0[3],const float t1[3],const float t2[3],float * depth)2028 bool ray_face_intersection_tri(const float ray_start[3],
2029 struct IsectRayPrecalc *isect_precalc,
2030 const float t0[3],
2031 const float t1[3],
2032 const float t2[3],
2033 float *depth)
2034 {
2035 float depth_test;
2036 if ((isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t1, t2, &depth_test, NULL) &&
2037 (depth_test < *depth))) {
2038 *depth = depth_test;
2039 return true;
2040 }
2041
2042 return false;
2043 }
2044
2045 /* Take advantage of the fact we know this wont be an intersection.
2046 * Just handle ray-tri edges. */
dist_squared_ray_to_tri_v3_fast(const float ray_origin[3],const float ray_direction[3],const float v0[3],const float v1[3],const float v2[3],float r_point[3],float * r_depth)2047 static float dist_squared_ray_to_tri_v3_fast(const float ray_origin[3],
2048 const float ray_direction[3],
2049 const float v0[3],
2050 const float v1[3],
2051 const float v2[3],
2052 float r_point[3],
2053 float *r_depth)
2054 {
2055 const float *tri[3] = {v0, v1, v2};
2056 float dist_sq_best = FLT_MAX;
2057 for (int i = 0, j = 2; i < 3; j = i++) {
2058 float point_test[3], depth_test = FLT_MAX;
2059 const float dist_sq_test = dist_squared_ray_to_seg_v3(
2060 ray_origin, ray_direction, tri[i], tri[j], point_test, &depth_test);
2061 if (dist_sq_test < dist_sq_best || i == 0) {
2062 copy_v3_v3(r_point, point_test);
2063 *r_depth = depth_test;
2064 dist_sq_best = dist_sq_test;
2065 }
2066 }
2067 return dist_sq_best;
2068 }
2069
ray_face_nearest_quad(const float ray_start[3],const float ray_normal[3],const float t0[3],const float t1[3],const float t2[3],const float t3[3],float * depth,float * dist_sq)2070 bool ray_face_nearest_quad(const float ray_start[3],
2071 const float ray_normal[3],
2072 const float t0[3],
2073 const float t1[3],
2074 const float t2[3],
2075 const float t3[3],
2076 float *depth,
2077 float *dist_sq)
2078 {
2079 float dist_sq_test;
2080 float co[3], depth_test;
2081
2082 if (((dist_sq_test = dist_squared_ray_to_tri_v3_fast(
2083 ray_start, ray_normal, t0, t1, t2, co, &depth_test)) < *dist_sq)) {
2084 *dist_sq = dist_sq_test;
2085 *depth = depth_test;
2086 if (((dist_sq_test = dist_squared_ray_to_tri_v3_fast(
2087 ray_start, ray_normal, t0, t2, t3, co, &depth_test)) < *dist_sq)) {
2088 *dist_sq = dist_sq_test;
2089 *depth = depth_test;
2090 }
2091 return true;
2092 }
2093
2094 return false;
2095 }
2096
ray_face_nearest_tri(const float ray_start[3],const float ray_normal[3],const float t0[3],const float t1[3],const float t2[3],float * depth,float * dist_sq)2097 bool ray_face_nearest_tri(const float ray_start[3],
2098 const float ray_normal[3],
2099 const float t0[3],
2100 const float t1[3],
2101 const float t2[3],
2102 float *depth,
2103 float *dist_sq)
2104 {
2105 float dist_sq_test;
2106 float co[3], depth_test;
2107
2108 if (((dist_sq_test = dist_squared_ray_to_tri_v3_fast(
2109 ray_start, ray_normal, t0, t1, t2, co, &depth_test)) < *dist_sq)) {
2110 *dist_sq = dist_sq_test;
2111 *depth = depth_test;
2112 return true;
2113 }
2114
2115 return false;
2116 }
2117
pbvh_faces_node_raycast(PBVH * pbvh,const PBVHNode * node,float (* origco)[3],const float ray_start[3],const float ray_normal[3],struct IsectRayPrecalc * isect_precalc,float * depth,int * r_active_vertex_index,int * r_active_face_index,float * r_face_normal)2118 static bool pbvh_faces_node_raycast(PBVH *pbvh,
2119 const PBVHNode *node,
2120 float (*origco)[3],
2121 const float ray_start[3],
2122 const float ray_normal[3],
2123 struct IsectRayPrecalc *isect_precalc,
2124 float *depth,
2125 int *r_active_vertex_index,
2126 int *r_active_face_index,
2127 float *r_face_normal)
2128 {
2129 const MVert *vert = pbvh->verts;
2130 const MLoop *mloop = pbvh->mloop;
2131 const int *faces = node->prim_indices;
2132 int totface = node->totprim;
2133 bool hit = false;
2134 float nearest_vertex_co[3] = {0.0f};
2135
2136 for (int i = 0; i < totface; i++) {
2137 const MLoopTri *lt = &pbvh->looptri[faces[i]];
2138 const int *face_verts = node->face_vert_indices[i];
2139
2140 if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
2141 continue;
2142 }
2143
2144 const float *co[3];
2145 if (origco) {
2146 /* intersect with backuped original coordinates */
2147 co[0] = origco[face_verts[0]];
2148 co[1] = origco[face_verts[1]];
2149 co[2] = origco[face_verts[2]];
2150 }
2151 else {
2152 /* intersect with current coordinates */
2153 co[0] = vert[mloop[lt->tri[0]].v].co;
2154 co[1] = vert[mloop[lt->tri[1]].v].co;
2155 co[2] = vert[mloop[lt->tri[2]].v].co;
2156 }
2157
2158 if (ray_face_intersection_tri(ray_start, isect_precalc, co[0], co[1], co[2], depth)) {
2159 hit = true;
2160
2161 if (r_face_normal) {
2162 normal_tri_v3(r_face_normal, co[0], co[1], co[2]);
2163 }
2164
2165 if (r_active_vertex_index) {
2166 float location[3] = {0.0f};
2167 madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
2168 for (int j = 0; j < 3; j++) {
2169 /* Always assign nearest_vertex_co in the first iteration to avoid comparison against
2170 * uninitialized values. This stores the closest vertex in the current intersecting
2171 * triangle. */
2172 if (j == 0 ||
2173 len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
2174 copy_v3_v3(nearest_vertex_co, co[j]);
2175 *r_active_vertex_index = mloop[lt->tri[j]].v;
2176 *r_active_face_index = lt->poly;
2177 }
2178 }
2179 }
2180 }
2181 }
2182
2183 return hit;
2184 }
2185
pbvh_grids_node_raycast(PBVH * pbvh,PBVHNode * node,float (* origco)[3],const float ray_start[3],const float ray_normal[3],struct IsectRayPrecalc * isect_precalc,float * depth,int * r_active_vertex_index,int * r_active_grid_index,float * r_face_normal)2186 static bool pbvh_grids_node_raycast(PBVH *pbvh,
2187 PBVHNode *node,
2188 float (*origco)[3],
2189 const float ray_start[3],
2190 const float ray_normal[3],
2191 struct IsectRayPrecalc *isect_precalc,
2192 float *depth,
2193 int *r_active_vertex_index,
2194 int *r_active_grid_index,
2195 float *r_face_normal)
2196 {
2197 const int totgrid = node->totprim;
2198 const int gridsize = pbvh->gridkey.grid_size;
2199 bool hit = false;
2200 float nearest_vertex_co[3] = {0.0};
2201 const CCGKey *gridkey = &pbvh->gridkey;
2202
2203 for (int i = 0; i < totgrid; i++) {
2204 const int grid_index = node->prim_indices[i];
2205 CCGElem *grid = pbvh->grids[grid_index];
2206 BLI_bitmap *gh;
2207
2208 if (!grid) {
2209 continue;
2210 }
2211
2212 gh = pbvh->grid_hidden[grid_index];
2213
2214 for (int y = 0; y < gridsize - 1; y++) {
2215 for (int x = 0; x < gridsize - 1; x++) {
2216 /* check if grid face is hidden */
2217 if (gh) {
2218 if (paint_is_grid_face_hidden(gh, gridsize, x, y)) {
2219 continue;
2220 }
2221 }
2222
2223 const float *co[4];
2224 if (origco) {
2225 co[0] = origco[y * gridsize + x];
2226 co[1] = origco[y * gridsize + x + 1];
2227 co[2] = origco[(y + 1) * gridsize + x + 1];
2228 co[3] = origco[(y + 1) * gridsize + x];
2229 }
2230 else {
2231 co[0] = CCG_grid_elem_co(gridkey, grid, x, y);
2232 co[1] = CCG_grid_elem_co(gridkey, grid, x + 1, y);
2233 co[2] = CCG_grid_elem_co(gridkey, grid, x + 1, y + 1);
2234 co[3] = CCG_grid_elem_co(gridkey, grid, x, y + 1);
2235 }
2236
2237 if (ray_face_intersection_quad(
2238 ray_start, isect_precalc, co[0], co[1], co[2], co[3], depth)) {
2239 hit = true;
2240
2241 if (r_face_normal) {
2242 normal_quad_v3(r_face_normal, co[0], co[1], co[2], co[3]);
2243 }
2244
2245 if (r_active_vertex_index) {
2246 float location[3] = {0.0};
2247 madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
2248
2249 const int x_it[4] = {0, 1, 1, 0};
2250 const int y_it[4] = {0, 0, 1, 1};
2251
2252 for (int j = 0; j < 4; j++) {
2253 /* Always assign nearest_vertex_co in the first iteration to avoid comparison against
2254 * uninitialized values. This stores the closest vertex in the current intersecting
2255 * quad. */
2256 if (j == 0 || len_squared_v3v3(location, co[j]) <
2257 len_squared_v3v3(location, nearest_vertex_co)) {
2258 copy_v3_v3(nearest_vertex_co, co[j]);
2259
2260 *r_active_vertex_index = gridkey->grid_area * grid_index +
2261 (y + y_it[j]) * gridkey->grid_size + (x + x_it[j]);
2262 }
2263 }
2264 }
2265 if (r_active_grid_index) {
2266 *r_active_grid_index = grid_index;
2267 }
2268 }
2269 }
2270 }
2271
2272 if (origco) {
2273 origco += gridsize * gridsize;
2274 }
2275 }
2276
2277 return hit;
2278 }
2279
BKE_pbvh_node_raycast(PBVH * pbvh,PBVHNode * node,float (* origco)[3],bool use_origco,const float ray_start[3],const float ray_normal[3],struct IsectRayPrecalc * isect_precalc,float * depth,int * active_vertex_index,int * active_face_grid_index,float * face_normal)2280 bool BKE_pbvh_node_raycast(PBVH *pbvh,
2281 PBVHNode *node,
2282 float (*origco)[3],
2283 bool use_origco,
2284 const float ray_start[3],
2285 const float ray_normal[3],
2286 struct IsectRayPrecalc *isect_precalc,
2287 float *depth,
2288 int *active_vertex_index,
2289 int *active_face_grid_index,
2290 float *face_normal)
2291 {
2292 bool hit = false;
2293
2294 if (node->flag & PBVH_FullyHidden) {
2295 return false;
2296 }
2297
2298 switch (pbvh->type) {
2299 case PBVH_FACES:
2300 hit |= pbvh_faces_node_raycast(pbvh,
2301 node,
2302 origco,
2303 ray_start,
2304 ray_normal,
2305 isect_precalc,
2306 depth,
2307 active_vertex_index,
2308 active_face_grid_index,
2309 face_normal);
2310 break;
2311 case PBVH_GRIDS:
2312 hit |= pbvh_grids_node_raycast(pbvh,
2313 node,
2314 origco,
2315 ray_start,
2316 ray_normal,
2317 isect_precalc,
2318 depth,
2319 active_vertex_index,
2320 active_face_grid_index,
2321 face_normal);
2322 break;
2323 case PBVH_BMESH:
2324 BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT);
2325 hit = pbvh_bmesh_node_raycast(node,
2326 ray_start,
2327 ray_normal,
2328 isect_precalc,
2329 depth,
2330 use_origco,
2331 active_vertex_index,
2332 face_normal);
2333 break;
2334 }
2335
2336 return hit;
2337 }
2338
BKE_pbvh_raycast_project_ray_root(PBVH * pbvh,bool original,float ray_start[3],float ray_end[3],float ray_normal[3])2339 void BKE_pbvh_raycast_project_ray_root(
2340 PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
2341 {
2342 if (pbvh->nodes) {
2343 float rootmin_start, rootmin_end;
2344 float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
2345 struct IsectRayAABB_Precalc ray;
2346 float ray_normal_inv[3];
2347 float offset = 1.0f + 1e-3f;
2348 const float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
2349
2350 if (original) {
2351 BKE_pbvh_node_get_original_BB(pbvh->nodes, bb_min_root, bb_max_root);
2352 }
2353 else {
2354 BKE_pbvh_node_get_BB(pbvh->nodes, bb_min_root, bb_max_root);
2355 }
2356
2357 /* Slightly offset min and max in case we have a zero width node
2358 * (due to a plane mesh for instance), or faces very close to the bounding box boundary. */
2359 mid_v3_v3v3(bb_center, bb_max_root, bb_min_root);
2360 /* diff should be same for both min/max since it's calculated from center */
2361 sub_v3_v3v3(bb_diff, bb_max_root, bb_center);
2362 /* handles case of zero width bb */
2363 add_v3_v3(bb_diff, offset_vec);
2364 madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset);
2365 madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset);
2366
2367 /* first project start ray */
2368 isect_ray_aabb_v3_precalc(&ray, ray_start, ray_normal);
2369 if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_start)) {
2370 return;
2371 }
2372
2373 /* then the end ray */
2374 mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0);
2375 isect_ray_aabb_v3_precalc(&ray, ray_end, ray_normal_inv);
2376 /* unlikely to fail exiting if entering succeeded, still keep this here */
2377 if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_end)) {
2378 return;
2379 }
2380
2381 madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start);
2382 madd_v3_v3v3fl(ray_end, ray_end, ray_normal_inv, rootmin_end);
2383 }
2384 }
2385
2386 /* -------------------------------------------------------------------- */
2387
2388 typedef struct {
2389 struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
2390 bool original;
2391 } FindNearestRayData;
2392
nearest_to_ray_aabb_dist_sq(PBVHNode * node,void * data_v)2393 static bool nearest_to_ray_aabb_dist_sq(PBVHNode *node, void *data_v)
2394 {
2395 FindNearestRayData *rcd = data_v;
2396 const float *bb_min, *bb_max;
2397
2398 if (rcd->original) {
2399 /* BKE_pbvh_node_get_original_BB */
2400 bb_min = node->orig_vb.bmin;
2401 bb_max = node->orig_vb.bmax;
2402 }
2403 else {
2404 /* BKE_pbvh_node_get_BB */
2405 bb_min = node->vb.bmin;
2406 bb_max = node->vb.bmax;
2407 }
2408
2409 float co_dummy[3], depth;
2410 node->tmin = dist_squared_ray_to_aabb_v3(
2411 &rcd->dist_ray_to_aabb_precalc, bb_min, bb_max, co_dummy, &depth);
2412 /* Ideally we would skip distances outside the range. */
2413 return depth > 0.0f;
2414 }
2415
BKE_pbvh_find_nearest_to_ray(PBVH * pbvh,BKE_pbvh_SearchNearestCallback cb,void * data,const float ray_start[3],const float ray_normal[3],bool original)2416 void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,
2417 BKE_pbvh_SearchNearestCallback cb,
2418 void *data,
2419 const float ray_start[3],
2420 const float ray_normal[3],
2421 bool original)
2422 {
2423 FindNearestRayData ncd;
2424
2425 dist_squared_ray_to_aabb_v3_precalc(&ncd.dist_ray_to_aabb_precalc, ray_start, ray_normal);
2426 ncd.original = original;
2427
2428 BKE_pbvh_search_callback_occluded(pbvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data);
2429 }
2430
pbvh_faces_node_nearest_to_ray(PBVH * pbvh,const PBVHNode * node,float (* origco)[3],const float ray_start[3],const float ray_normal[3],float * depth,float * dist_sq)2431 static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
2432 const PBVHNode *node,
2433 float (*origco)[3],
2434 const float ray_start[3],
2435 const float ray_normal[3],
2436 float *depth,
2437 float *dist_sq)
2438 {
2439 const MVert *vert = pbvh->verts;
2440 const MLoop *mloop = pbvh->mloop;
2441 const int *faces = node->prim_indices;
2442 int i, totface = node->totprim;
2443 bool hit = false;
2444
2445 for (i = 0; i < totface; i++) {
2446 const MLoopTri *lt = &pbvh->looptri[faces[i]];
2447 const int *face_verts = node->face_vert_indices[i];
2448
2449 if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
2450 continue;
2451 }
2452
2453 if (origco) {
2454 /* intersect with backuped original coordinates */
2455 hit |= ray_face_nearest_tri(ray_start,
2456 ray_normal,
2457 origco[face_verts[0]],
2458 origco[face_verts[1]],
2459 origco[face_verts[2]],
2460 depth,
2461 dist_sq);
2462 }
2463 else {
2464 /* intersect with current coordinates */
2465 hit |= ray_face_nearest_tri(ray_start,
2466 ray_normal,
2467 vert[mloop[lt->tri[0]].v].co,
2468 vert[mloop[lt->tri[1]].v].co,
2469 vert[mloop[lt->tri[2]].v].co,
2470 depth,
2471 dist_sq);
2472 }
2473 }
2474
2475 return hit;
2476 }
2477
pbvh_grids_node_nearest_to_ray(PBVH * pbvh,PBVHNode * node,float (* origco)[3],const float ray_start[3],const float ray_normal[3],float * depth,float * dist_sq)2478 static bool pbvh_grids_node_nearest_to_ray(PBVH *pbvh,
2479 PBVHNode *node,
2480 float (*origco)[3],
2481 const float ray_start[3],
2482 const float ray_normal[3],
2483 float *depth,
2484 float *dist_sq)
2485 {
2486 const int totgrid = node->totprim;
2487 const int gridsize = pbvh->gridkey.grid_size;
2488 bool hit = false;
2489
2490 for (int i = 0; i < totgrid; i++) {
2491 CCGElem *grid = pbvh->grids[node->prim_indices[i]];
2492 BLI_bitmap *gh;
2493
2494 if (!grid) {
2495 continue;
2496 }
2497
2498 gh = pbvh->grid_hidden[node->prim_indices[i]];
2499
2500 for (int y = 0; y < gridsize - 1; y++) {
2501 for (int x = 0; x < gridsize - 1; x++) {
2502 /* check if grid face is hidden */
2503 if (gh) {
2504 if (paint_is_grid_face_hidden(gh, gridsize, x, y)) {
2505 continue;
2506 }
2507 }
2508
2509 if (origco) {
2510 hit |= ray_face_nearest_quad(ray_start,
2511 ray_normal,
2512 origco[y * gridsize + x],
2513 origco[y * gridsize + x + 1],
2514 origco[(y + 1) * gridsize + x + 1],
2515 origco[(y + 1) * gridsize + x],
2516 depth,
2517 dist_sq);
2518 }
2519 else {
2520 hit |= ray_face_nearest_quad(ray_start,
2521 ray_normal,
2522 CCG_grid_elem_co(&pbvh->gridkey, grid, x, y),
2523 CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y),
2524 CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y + 1),
2525 CCG_grid_elem_co(&pbvh->gridkey, grid, x, y + 1),
2526 depth,
2527 dist_sq);
2528 }
2529 }
2530 }
2531
2532 if (origco) {
2533 origco += gridsize * gridsize;
2534 }
2535 }
2536
2537 return hit;
2538 }
2539
BKE_pbvh_node_find_nearest_to_ray(PBVH * pbvh,PBVHNode * node,float (* origco)[3],bool use_origco,const float ray_start[3],const float ray_normal[3],float * depth,float * dist_sq)2540 bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
2541 PBVHNode *node,
2542 float (*origco)[3],
2543 bool use_origco,
2544 const float ray_start[3],
2545 const float ray_normal[3],
2546 float *depth,
2547 float *dist_sq)
2548 {
2549 bool hit = false;
2550
2551 if (node->flag & PBVH_FullyHidden) {
2552 return false;
2553 }
2554
2555 switch (pbvh->type) {
2556 case PBVH_FACES:
2557 hit |= pbvh_faces_node_nearest_to_ray(
2558 pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
2559 break;
2560 case PBVH_GRIDS:
2561 hit |= pbvh_grids_node_nearest_to_ray(
2562 pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
2563 break;
2564 case PBVH_BMESH:
2565 hit = pbvh_bmesh_node_nearest_to_ray(
2566 node, ray_start, ray_normal, depth, dist_sq, use_origco);
2567 break;
2568 }
2569
2570 return hit;
2571 }
2572
2573 typedef enum {
2574 ISECT_INSIDE,
2575 ISECT_OUTSIDE,
2576 ISECT_INTERSECT,
2577 } PlaneAABBIsect;
2578
2579 /* Adapted from:
2580 * http://www.gamedev.net/community/forums/topic.asp?topic_id=512123
2581 * Returns true if the AABB is at least partially within the frustum
2582 * (ok, not a real frustum), false otherwise.
2583 */
test_frustum_aabb(const float bb_min[3],const float bb_max[3],PBVHFrustumPlanes * frustum)2584 static PlaneAABBIsect test_frustum_aabb(const float bb_min[3],
2585 const float bb_max[3],
2586 PBVHFrustumPlanes *frustum)
2587 {
2588 PlaneAABBIsect ret = ISECT_INSIDE;
2589 float(*planes)[4] = frustum->planes;
2590
2591 for (int i = 0; i < frustum->num_planes; i++) {
2592 float vmin[3], vmax[3];
2593
2594 for (int axis = 0; axis < 3; axis++) {
2595 if (planes[i][axis] < 0) {
2596 vmin[axis] = bb_min[axis];
2597 vmax[axis] = bb_max[axis];
2598 }
2599 else {
2600 vmin[axis] = bb_max[axis];
2601 vmax[axis] = bb_min[axis];
2602 }
2603 }
2604
2605 if (dot_v3v3(planes[i], vmin) + planes[i][3] < 0) {
2606 return ISECT_OUTSIDE;
2607 }
2608 if (dot_v3v3(planes[i], vmax) + planes[i][3] <= 0) {
2609 ret = ISECT_INTERSECT;
2610 }
2611 }
2612
2613 return ret;
2614 }
2615
BKE_pbvh_node_frustum_contain_AABB(PBVHNode * node,void * data)2616 bool BKE_pbvh_node_frustum_contain_AABB(PBVHNode *node, void *data)
2617 {
2618 const float *bb_min, *bb_max;
2619 /* BKE_pbvh_node_get_BB */
2620 bb_min = node->vb.bmin;
2621 bb_max = node->vb.bmax;
2622
2623 return test_frustum_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE;
2624 }
2625
BKE_pbvh_node_frustum_exclude_AABB(PBVHNode * node,void * data)2626 bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data)
2627 {
2628 const float *bb_min, *bb_max;
2629 /* BKE_pbvh_node_get_BB */
2630 bb_min = node->vb.bmin;
2631 bb_max = node->vb.bmax;
2632
2633 return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
2634 }
2635
BKE_pbvh_update_normals(PBVH * pbvh,struct SubdivCCG * subdiv_ccg)2636 void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg)
2637 {
2638 /* Update normals */
2639 PBVHNode **nodes;
2640 int totnode;
2641
2642 BKE_pbvh_search_gather(
2643 pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);
2644
2645 if (totnode > 0) {
2646 if (pbvh->type == PBVH_BMESH) {
2647 pbvh_bmesh_normals_update(nodes, totnode);
2648 }
2649 else if (pbvh->type == PBVH_FACES) {
2650 pbvh_faces_update_normals(pbvh, nodes, totnode);
2651 }
2652 else if (pbvh->type == PBVH_GRIDS) {
2653 struct CCGFace **faces;
2654 int num_faces;
2655 BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces);
2656 if (num_faces > 0) {
2657 BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
2658 MEM_freeN(faces);
2659 }
2660 }
2661 }
2662
2663 MEM_SAFE_FREE(nodes);
2664 }
2665
BKE_pbvh_face_sets_color_set(PBVH * pbvh,int seed,int color_default)2666 void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default)
2667 {
2668 pbvh->face_sets_color_seed = seed;
2669 pbvh->face_sets_color_default = color_default;
2670 }
2671
2672 /**
2673 * PBVH drawing, updating draw buffers as needed and culling any nodes outside
2674 * the specified frustum.
2675 */
2676 typedef struct PBVHDrawSearchData {
2677 PBVHFrustumPlanes *frustum;
2678 int accum_update_flag;
2679 } PBVHDrawSearchData;
2680
pbvh_draw_search_cb(PBVHNode * node,void * data_v)2681 static bool pbvh_draw_search_cb(PBVHNode *node, void *data_v)
2682 {
2683 PBVHDrawSearchData *data = data_v;
2684 if (data->frustum && !BKE_pbvh_node_frustum_contain_AABB(node, data->frustum)) {
2685 return false;
2686 }
2687
2688 data->accum_update_flag |= node->flag;
2689 return true;
2690 }
2691
BKE_pbvh_draw_cb(PBVH * pbvh,bool update_only_visible,PBVHFrustumPlanes * update_frustum,PBVHFrustumPlanes * draw_frustum,void (* draw_fn)(void * user_data,GPU_PBVH_Buffers * buffers),void * user_data)2692 void BKE_pbvh_draw_cb(PBVH *pbvh,
2693 bool update_only_visible,
2694 PBVHFrustumPlanes *update_frustum,
2695 PBVHFrustumPlanes *draw_frustum,
2696 void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers),
2697 void *user_data)
2698 {
2699 PBVHNode **nodes;
2700 int totnode;
2701
2702 const int update_flag = PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers;
2703
2704 if (!update_only_visible) {
2705 /* Update all draw buffers, also those outside the view. */
2706 BKE_pbvh_search_gather(
2707 pbvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode);
2708
2709 if (totnode) {
2710 pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag);
2711 }
2712
2713 MEM_SAFE_FREE(nodes);
2714 }
2715
2716 /* Gather visible nodes. */
2717 PBVHDrawSearchData data = {.frustum = update_frustum, .accum_update_flag = 0};
2718 BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &data, &nodes, &totnode);
2719
2720 if (update_only_visible && (data.accum_update_flag & update_flag)) {
2721 /* Update draw buffers in visible nodes. */
2722 pbvh_update_draw_buffers(pbvh, nodes, totnode, data.accum_update_flag);
2723 }
2724
2725 /* Draw. */
2726 for (int a = 0; a < totnode; a++) {
2727 PBVHNode *node = nodes[a];
2728
2729 if (node->flag & PBVH_UpdateDrawBuffers) {
2730 /* Flush buffers uses OpenGL, so not in parallel. */
2731 GPU_pbvh_buffers_update_flush(node->draw_buffers);
2732 }
2733
2734 node->flag &= ~(PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers);
2735 }
2736
2737 MEM_SAFE_FREE(nodes);
2738
2739 PBVHDrawSearchData draw_data = {.frustum = draw_frustum, .accum_update_flag = 0};
2740 BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode);
2741
2742 for (int a = 0; a < totnode; a++) {
2743 PBVHNode *node = nodes[a];
2744 if (!(node->flag & PBVH_FullyHidden)) {
2745 draw_fn(user_data, node->draw_buffers);
2746 }
2747 }
2748
2749 MEM_SAFE_FREE(nodes);
2750 }
2751
BKE_pbvh_draw_debug_cb(PBVH * pbvh,void (* draw_fn)(void * user_data,const float bmin[3],const float bmax[3],PBVHNodeFlags flag),void * user_data)2752 void BKE_pbvh_draw_debug_cb(
2753 PBVH *pbvh,
2754 void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
2755 void *user_data)
2756 {
2757 for (int a = 0; a < pbvh->totnode; a++) {
2758 PBVHNode *node = &pbvh->nodes[a];
2759
2760 draw_fn(user_data, node->vb.bmin, node->vb.bmax, node->flag);
2761 }
2762 }
2763
BKE_pbvh_grids_update(PBVH * pbvh,CCGElem ** grids,void ** gridfaces,DMFlagMat * flagmats,BLI_bitmap ** grid_hidden)2764 void BKE_pbvh_grids_update(
2765 PBVH *pbvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
2766 {
2767 pbvh->grids = grids;
2768 pbvh->gridfaces = gridfaces;
2769
2770 if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
2771 pbvh->grid_flag_mats = flagmats;
2772 pbvh->grid_hidden = grid_hidden;
2773
2774 for (int a = 0; a < pbvh->totnode; a++) {
2775 BKE_pbvh_node_mark_rebuild_draw(&pbvh->nodes[a]);
2776 }
2777 }
2778 }
2779
BKE_pbvh_vert_coords_alloc(PBVH * pbvh)2780 float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3]
2781 {
2782 float(*vertCos)[3] = NULL;
2783
2784 if (pbvh->verts) {
2785 MVert *mvert = pbvh->verts;
2786
2787 vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BKE_pbvh_get_vertCoords");
2788 float *co = (float *)vertCos;
2789
2790 for (int a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
2791 copy_v3_v3(co, mvert->co);
2792 }
2793 }
2794
2795 return vertCos;
2796 }
2797
BKE_pbvh_vert_coords_apply(PBVH * pbvh,const float (* vertCos)[3],const int totvert)2798 void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int totvert)
2799 {
2800 if (totvert != pbvh->totvert) {
2801 BLI_assert(!"PBVH: Given deforming vcos number does not natch PBVH vertex number!");
2802 return;
2803 }
2804
2805 if (!pbvh->deformed) {
2806 if (pbvh->verts) {
2807 /* if pbvh is not already deformed, verts/faces points to the */
2808 /* original data and applying new coords to this arrays would lead to */
2809 /* unneeded deformation -- duplicate verts/faces to avoid this */
2810
2811 pbvh->verts = MEM_dupallocN(pbvh->verts);
2812 /* No need to dupalloc pbvh->looptri, this one is 'totally owned' by pbvh,
2813 * it's never some mesh data. */
2814
2815 pbvh->deformed = true;
2816 }
2817 }
2818
2819 if (pbvh->verts) {
2820 MVert *mvert = pbvh->verts;
2821 /* copy new verts coords */
2822 for (int a = 0; a < pbvh->totvert; a++, mvert++) {
2823 /* no need for float comparison here (memory is exactly equal or not) */
2824 if (memcmp(mvert->co, vertCos[a], sizeof(float[3])) != 0) {
2825 copy_v3_v3(mvert->co, vertCos[a]);
2826 mvert->flag |= ME_VERT_PBVH_UPDATE;
2827 }
2828 }
2829
2830 /* coordinates are new -- normals should also be updated */
2831 BKE_mesh_calc_normals_looptri(
2832 pbvh->verts, pbvh->totvert, pbvh->mloop, pbvh->looptri, pbvh->totprim, NULL);
2833
2834 for (int a = 0; a < pbvh->totnode; a++) {
2835 BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
2836 }
2837
2838 BKE_pbvh_update_bounds(pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB);
2839 }
2840 }
2841
BKE_pbvh_is_deformed(PBVH * pbvh)2842 bool BKE_pbvh_is_deformed(PBVH *pbvh)
2843 {
2844 return pbvh->deformed;
2845 }
2846 /* Proxies */
2847
BKE_pbvh_node_add_proxy(PBVH * pbvh,PBVHNode * node)2848 PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
2849 {
2850 int index, totverts;
2851
2852 index = node->proxy_count;
2853
2854 node->proxy_count++;
2855
2856 if (node->proxies) {
2857 node->proxies = MEM_reallocN(node->proxies, node->proxy_count * sizeof(PBVHProxyNode));
2858 }
2859 else {
2860 node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
2861 }
2862
2863 BKE_pbvh_node_num_verts(pbvh, node, &totverts, NULL);
2864 node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co");
2865
2866 return node->proxies + index;
2867 }
2868
BKE_pbvh_node_free_proxies(PBVHNode * node)2869 void BKE_pbvh_node_free_proxies(PBVHNode *node)
2870 {
2871 for (int p = 0; p < node->proxy_count; p++) {
2872 MEM_freeN(node->proxies[p].co);
2873 node->proxies[p].co = NULL;
2874 }
2875
2876 MEM_freeN(node->proxies);
2877 node->proxies = NULL;
2878
2879 node->proxy_count = 0;
2880 }
2881
BKE_pbvh_gather_proxies(PBVH * pbvh,PBVHNode *** r_array,int * r_tot)2882 void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
2883 {
2884 PBVHNode **array = NULL;
2885 int tot = 0, space = 0;
2886
2887 for (int n = 0; n < pbvh->totnode; n++) {
2888 PBVHNode *node = pbvh->nodes + n;
2889
2890 if (node->proxy_count > 0) {
2891 if (tot == space) {
2892 /* resize array if needed */
2893 space = (tot == 0) ? 32 : space * 2;
2894 array = MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__);
2895 }
2896
2897 array[tot] = node;
2898 tot++;
2899 }
2900 }
2901
2902 if (tot == 0 && array) {
2903 MEM_freeN(array);
2904 array = NULL;
2905 }
2906
2907 *r_array = array;
2908 *r_tot = tot;
2909 }
2910
BKE_pbvh_node_color_buffer_get(PBVHNode * node)2911 PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node)
2912 {
2913
2914 if (!node->color_buffer.color) {
2915 node->color_buffer.color = MEM_callocN(sizeof(float[4]) * node->uniq_verts, "Color buffer");
2916 }
2917 return &node->color_buffer;
2918 }
2919
BKE_pbvh_node_color_buffer_free(PBVH * pbvh)2920 void BKE_pbvh_node_color_buffer_free(PBVH *pbvh)
2921 {
2922 PBVHNode **nodes;
2923 int totnode;
2924 BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
2925 for (int i = 0; i < totnode; i++) {
2926 MEM_SAFE_FREE(nodes[i]->color_buffer.color);
2927 }
2928 MEM_SAFE_FREE(nodes);
2929 }
2930
pbvh_vertex_iter_init(PBVH * pbvh,PBVHNode * node,PBVHVertexIter * vi,int mode)2931 void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
2932 {
2933 struct CCGElem **grids;
2934 struct MVert *verts;
2935 const int *vert_indices;
2936 int *grid_indices;
2937 int totgrid, gridsize, uniq_verts, totvert;
2938
2939 vi->grid = NULL;
2940 vi->no = NULL;
2941 vi->fno = NULL;
2942 vi->mvert = NULL;
2943
2944 vi->respect_hide = pbvh->respect_hide;
2945 if (pbvh->respect_hide == false) {
2946 /* The same value for all vertices. */
2947 vi->visible = true;
2948 }
2949
2950 BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
2951 BKE_pbvh_node_num_verts(pbvh, node, &uniq_verts, &totvert);
2952 BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &verts);
2953 vi->key = pbvh->gridkey;
2954
2955 vi->grids = grids;
2956 vi->grid_indices = grid_indices;
2957 vi->totgrid = (grids) ? totgrid : 1;
2958 vi->gridsize = gridsize;
2959
2960 if (mode == PBVH_ITER_ALL) {
2961 vi->totvert = totvert;
2962 }
2963 else {
2964 vi->totvert = uniq_verts;
2965 }
2966 vi->vert_indices = vert_indices;
2967 vi->mverts = verts;
2968
2969 if (pbvh->type == PBVH_BMESH) {
2970 BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
2971 BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts);
2972 vi->bm_vdata = &pbvh->bm->vdata;
2973 vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
2974 }
2975
2976 vi->gh = NULL;
2977 if (vi->grids && mode == PBVH_ITER_UNIQUE) {
2978 vi->grid_hidden = pbvh->grid_hidden;
2979 }
2980
2981 vi->mask = NULL;
2982 if (pbvh->type == PBVH_FACES) {
2983 vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK);
2984 vi->vcol = CustomData_get_layer(pbvh->vdata, CD_PROP_COLOR);
2985 }
2986 }
2987
pbvh_has_mask(PBVH * pbvh)2988 bool pbvh_has_mask(PBVH *pbvh)
2989 {
2990 switch (pbvh->type) {
2991 case PBVH_GRIDS:
2992 return (pbvh->gridkey.has_mask != 0);
2993 case PBVH_FACES:
2994 return (pbvh->vdata && CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK));
2995 case PBVH_BMESH:
2996 return (pbvh->bm && (CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK) != -1));
2997 }
2998
2999 return false;
3000 }
3001
pbvh_has_face_sets(PBVH * pbvh)3002 bool pbvh_has_face_sets(PBVH *pbvh)
3003 {
3004 switch (pbvh->type) {
3005 case PBVH_GRIDS:
3006 return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
3007 case PBVH_FACES:
3008 return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
3009 case PBVH_BMESH:
3010 return false;
3011 }
3012
3013 return false;
3014 }
3015
pbvh_show_mask_set(PBVH * pbvh,bool show_mask)3016 void pbvh_show_mask_set(PBVH *pbvh, bool show_mask)
3017 {
3018 pbvh->show_mask = show_mask;
3019 }
3020
pbvh_show_face_sets_set(PBVH * pbvh,bool show_face_sets)3021 void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets)
3022 {
3023 pbvh->show_face_sets = show_face_sets;
3024 }
3025
BKE_pbvh_set_frustum_planes(PBVH * pbvh,PBVHFrustumPlanes * planes)3026 void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
3027 {
3028 pbvh->num_planes = planes->num_planes;
3029 for (int i = 0; i < pbvh->num_planes; i++) {
3030 copy_v4_v4(pbvh->planes[i], planes->planes[i]);
3031 }
3032 }
3033
BKE_pbvh_get_frustum_planes(PBVH * pbvh,PBVHFrustumPlanes * planes)3034 void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
3035 {
3036 planes->num_planes = pbvh->num_planes;
3037 for (int i = 0; i < planes->num_planes; i++) {
3038 copy_v4_v4(planes->planes[i], pbvh->planes[i]);
3039 }
3040 }
3041
BKE_pbvh_parallel_range_settings(TaskParallelSettings * settings,bool use_threading,int totnode)3042 void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
3043 bool use_threading,
3044 int totnode)
3045 {
3046 memset(settings, 0, sizeof(*settings));
3047 settings->use_threading = use_threading && totnode > 1;
3048 }
3049
BKE_pbvh_get_verts(const PBVH * pbvh)3050 MVert *BKE_pbvh_get_verts(const PBVH *pbvh)
3051 {
3052 BLI_assert(pbvh->type == PBVH_FACES);
3053 return pbvh->verts;
3054 }
3055
BKE_pbvh_subdiv_cgg_set(PBVH * pbvh,SubdivCCG * subdiv_ccg)3056 void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
3057 {
3058 pbvh->subdiv_ccg = subdiv_ccg;
3059 }
3060
BKE_pbvh_face_sets_set(PBVH * pbvh,int * face_sets)3061 void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets)
3062 {
3063 pbvh->face_sets = face_sets;
3064 }
3065
BKE_pbvh_respect_hide_set(PBVH * pbvh,bool respect_hide)3066 void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
3067 {
3068 pbvh->respect_hide = respect_hide;
3069 }
3070