|
Blender
V2.59
|
00001 /* 00002 * $Id: pbvh.c 38867 2011-07-31 02:34:53Z nicholasbishop $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00029 #include "DNA_meshdata_types.h" 00030 00031 #include "MEM_guardedalloc.h" 00032 00033 #include "BLI_math.h" 00034 #include "BLI_utildefines.h" 00035 #include "BLI_ghash.h" 00036 #include "BLI_pbvh.h" 00037 00038 #include "BKE_DerivedMesh.h" 00039 #include "BKE_mesh.h" /* for mesh_calc_normals */ 00040 #include "BKE_global.h" /* for mesh_calc_normals */ 00041 00042 #include "GPU_buffers.h" 00043 00044 #define LEAF_LIMIT 10000 00045 00046 //#define PERFCNTRS 00047 00048 /* Bitmap */ 00049 typedef char* BLI_bitmap; 00050 00051 static BLI_bitmap BLI_bitmap_new(int tot) 00052 { 00053 return MEM_callocN((tot >> 3) + 1, "BLI bitmap"); 00054 } 00055 00056 static int BLI_bitmap_get(BLI_bitmap b, int index) 00057 { 00058 return b[index >> 3] & (1 << (index & 7)); 00059 } 00060 00061 static void BLI_bitmap_set(BLI_bitmap b, int index) 00062 { 00063 b[index >> 3] |= (1 << (index & 7)); 00064 } 00065 00066 #if 0 /* UNUSED */ 00067 static void BLI_bitmap_clear(BLI_bitmap b, int index) 00068 { 00069 b[index >> 3] &= ~(1 << (index & 7)); 00070 } 00071 #endif 00072 00073 /* Axis-aligned bounding box */ 00074 typedef struct { 00075 float bmin[3], bmax[3]; 00076 } BB; 00077 00078 /* Axis-aligned bounding box with centroid */ 00079 typedef struct { 00080 float bmin[3], bmax[3], bcentroid[3]; 00081 } BBC; 00082 00083 struct PBVHNode { 00084 /* Opaque handle for drawing code */ 00085 void *draw_buffers; 00086 00087 /* Voxel bounds */ 00088 BB vb; 00089 BB orig_vb; 00090 00091 /* For internal nodes, the offset of the children in the PBVH 00092 'nodes' array. */ 00093 int children_offset; 00094 00095 /* Pointer into the PBVH prim_indices array and the number of 00096 primitives used by this leaf node. 00097 00098 Used for leaf nodes in both mesh- and multires-based PBVHs. 00099 */ 00100 int *prim_indices; 00101 unsigned int totprim; 00102 00103 /* Array of indices into the mesh's MVert array. Contains the 00104 indices of all vertices used by faces that are within this 00105 node's bounding box. 00106 00107 Note that a vertex might be used by a multiple faces, and 00108 these faces might be in different leaf nodes. Such a vertex 00109 will appear in the vert_indices array of each of those leaf 00110 nodes. 00111 00112 In order to support cases where you want access to multiple 00113 nodes' vertices without duplication, the vert_indices array 00114 is ordered such that the first part of the array, up to 00115 index 'uniq_verts', contains "unique" vertex indices. These 00116 vertices might not be truly unique to this node, but if 00117 they appear in another node's vert_indices array, they will 00118 be above that node's 'uniq_verts' value. 00119 00120 Used for leaf nodes in a mesh-based PBVH (not multires.) 00121 */ 00122 int *vert_indices; 00123 unsigned int uniq_verts, face_verts; 00124 00125 /* An array mapping face corners into the vert_indices 00126 array. The array is sized to match 'totprim', and each of 00127 the face's corners gets an index into the vert_indices 00128 array, in the same order as the corners in the original 00129 MFace. The fourth value should not be used if the original 00130 face is a triangle. 00131 00132 Used for leaf nodes in a mesh-based PBVH (not multires.) 00133 */ 00134 int (*face_vert_indices)[4]; 00135 00136 /* Indicates whether this node is a leaf or not; also used for 00137 marking various updates that need to be applied. */ 00138 PBVHNodeFlags flag : 8; 00139 00140 /* Used for raycasting: how close bb is to the ray point. */ 00141 float tmin; 00142 00143 int proxy_count; 00144 PBVHProxyNode* proxies; 00145 }; 00146 00147 struct PBVH { 00148 PBVHNode *nodes; 00149 int node_mem_count, totnode; 00150 00151 int *prim_indices; 00152 int totprim; 00153 int totvert; 00154 00155 int leaf_limit; 00156 00157 /* Mesh data */ 00158 MVert *verts; 00159 MFace *faces; 00160 00161 /* Grid Data */ 00162 DMGridData **grids; 00163 DMGridAdjacency *gridadj; 00164 void **gridfaces; 00165 int totgrid; 00166 int gridsize; 00167 00168 /* Only used during BVH build and update, 00169 don't need to remain valid after */ 00170 BLI_bitmap vert_bitmap; 00171 00172 #ifdef PERFCNTRS 00173 int perf_modified; 00174 #endif 00175 00176 /* flag are verts/faces deformed */ 00177 int deformed; 00178 }; 00179 00180 #define STACK_FIXED_DEPTH 100 00181 00182 typedef struct PBVHStack { 00183 PBVHNode *node; 00184 int revisiting; 00185 } PBVHStack; 00186 00187 typedef struct PBVHIter { 00188 PBVH *bvh; 00189 BLI_pbvh_SearchCallback scb; 00190 void *search_data; 00191 00192 PBVHStack *stack; 00193 int stacksize; 00194 00195 PBVHStack stackfixed[STACK_FIXED_DEPTH]; 00196 int stackspace; 00197 } PBVHIter; 00198 00199 static void BB_reset(BB *bb) 00200 { 00201 bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX; 00202 bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX; 00203 } 00204 00205 /* Expand the bounding box to include a new coordinate */ 00206 static void BB_expand(BB *bb, float co[3]) 00207 { 00208 int i; 00209 for(i = 0; i < 3; ++i) { 00210 bb->bmin[i] = MIN2(bb->bmin[i], co[i]); 00211 bb->bmax[i] = MAX2(bb->bmax[i], co[i]); 00212 } 00213 } 00214 00215 /* Expand the bounding box to include another bounding box */ 00216 static void BB_expand_with_bb(BB *bb, BB *bb2) 00217 { 00218 int i; 00219 for(i = 0; i < 3; ++i) { 00220 bb->bmin[i] = MIN2(bb->bmin[i], bb2->bmin[i]); 00221 bb->bmax[i] = MAX2(bb->bmax[i], bb2->bmax[i]); 00222 } 00223 } 00224 00225 /* Return 0, 1, or 2 to indicate the widest axis of the bounding box */ 00226 static int BB_widest_axis(BB *bb) 00227 { 00228 float dim[3]; 00229 int i; 00230 00231 for(i = 0; i < 3; ++i) 00232 dim[i] = bb->bmax[i] - bb->bmin[i]; 00233 00234 if(dim[0] > dim[1]) { 00235 if(dim[0] > dim[2]) 00236 return 0; 00237 else 00238 return 2; 00239 } 00240 else { 00241 if(dim[1] > dim[2]) 00242 return 1; 00243 else 00244 return 2; 00245 } 00246 } 00247 00248 static void BBC_update_centroid(BBC *bbc) 00249 { 00250 int i; 00251 for(i = 0; i < 3; ++i) 00252 bbc->bcentroid[i] = (bbc->bmin[i] + bbc->bmax[i]) * 0.5f; 00253 } 00254 00255 /* Not recursive */ 00256 static void update_node_vb(PBVH *bvh, PBVHNode *node) 00257 { 00258 BB vb; 00259 00260 BB_reset(&vb); 00261 00262 if(node->flag & PBVH_Leaf) { 00263 PBVHVertexIter vd; 00264 00265 BLI_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) { 00266 BB_expand(&vb, vd.co); 00267 } 00268 BLI_pbvh_vertex_iter_end; 00269 } 00270 else { 00271 BB_expand_with_bb(&vb, 00272 &bvh->nodes[node->children_offset].vb); 00273 BB_expand_with_bb(&vb, 00274 &bvh->nodes[node->children_offset + 1].vb); 00275 } 00276 00277 node->vb= vb; 00278 } 00279 00280 //void BLI_pbvh_node_BB_reset(PBVHNode* node) 00281 //{ 00282 // BB_reset(&node->vb); 00283 //} 00284 // 00285 //void BLI_pbvh_node_BB_expand(PBVHNode* node, float co[3]) 00286 //{ 00287 // BB_expand(&node->vb, co); 00288 //} 00289 00290 00291 /* Adapted from BLI_kdopbvh.c */ 00292 /* Returns the index of the first element on the right of the partition */ 00293 static int partition_indices(int *prim_indices, int lo, int hi, int axis, 00294 float mid, BBC *prim_bbc) 00295 { 00296 int i=lo, j=hi; 00297 for(;;) { 00298 for(; prim_bbc[prim_indices[i]].bcentroid[axis] < mid; i++); 00299 for(; mid < prim_bbc[prim_indices[j]].bcentroid[axis]; j--); 00300 00301 if(!(i < j)) 00302 return i; 00303 00304 SWAP(int, prim_indices[i], prim_indices[j]); 00305 i++; 00306 } 00307 } 00308 00309 static void check_partitioning(int *prim_indices, int lo, int hi, int axis, 00310 float mid, BBC *prim_bbc, int index_of_2nd_partition) 00311 { 00312 int i; 00313 for(i = lo; i <= hi; ++i) { 00314 const float c = prim_bbc[prim_indices[i]].bcentroid[axis]; 00315 00316 if((i < index_of_2nd_partition && c > mid) || 00317 (i > index_of_2nd_partition && c < mid)) { 00318 printf("fail\n"); 00319 } 00320 } 00321 } 00322 00323 static void grow_nodes(PBVH *bvh, int totnode) 00324 { 00325 if(totnode > bvh->node_mem_count) { 00326 PBVHNode *prev = bvh->nodes; 00327 bvh->node_mem_count *= 1.33; 00328 if(bvh->node_mem_count < totnode) 00329 bvh->node_mem_count = totnode; 00330 bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count, 00331 "bvh nodes"); 00332 memcpy(bvh->nodes, prev, bvh->totnode * sizeof(PBVHNode)); 00333 MEM_freeN(prev); 00334 } 00335 00336 bvh->totnode = totnode; 00337 } 00338 00339 /* Add a vertex to the map, with a positive value for unique vertices and 00340 a negative value for additional vertices */ 00341 static int map_insert_vert(PBVH *bvh, GHash *map, 00342 unsigned int *face_verts, 00343 unsigned int *uniq_verts, int vertex) 00344 { 00345 void *value, *key = SET_INT_IN_POINTER(vertex); 00346 00347 if(!BLI_ghash_haskey(map, key)) { 00348 if(BLI_bitmap_get(bvh->vert_bitmap, vertex)) { 00349 value = SET_INT_IN_POINTER(-(*face_verts) - 1); 00350 ++(*face_verts); 00351 } 00352 else { 00353 BLI_bitmap_set(bvh->vert_bitmap, vertex); 00354 value = SET_INT_IN_POINTER(*uniq_verts); 00355 ++(*uniq_verts); 00356 } 00357 00358 BLI_ghash_insert(map, key, value); 00359 return GET_INT_FROM_POINTER(value); 00360 } 00361 else 00362 return GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key)); 00363 } 00364 00365 /* Find vertices used by the faces in this node and update the draw buffers */ 00366 static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) 00367 { 00368 GHashIterator *iter; 00369 GHash *map; 00370 int i, j, totface; 00371 00372 map = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "build_mesh_leaf_node gh"); 00373 00374 node->uniq_verts = node->face_verts = 0; 00375 totface= node->totprim; 00376 00377 node->face_vert_indices = MEM_callocN(sizeof(int) * 4*totface, 00378 "bvh node face vert indices"); 00379 00380 for(i = 0; i < totface; ++i) { 00381 MFace *f = bvh->faces + node->prim_indices[i]; 00382 int sides = f->v4 ? 4 : 3; 00383 00384 for(j = 0; j < sides; ++j) { 00385 node->face_vert_indices[i][j]= 00386 map_insert_vert(bvh, map, &node->face_verts, 00387 &node->uniq_verts, (&f->v1)[j]); 00388 } 00389 } 00390 00391 node->vert_indices = MEM_callocN(sizeof(int) * 00392 (node->uniq_verts + node->face_verts), 00393 "bvh node vert indices"); 00394 00395 /* Build the vertex list, unique verts first */ 00396 for(iter = BLI_ghashIterator_new(map), i = 0; 00397 !BLI_ghashIterator_isDone(iter); 00398 BLI_ghashIterator_step(iter), ++i) { 00399 void *value = BLI_ghashIterator_getValue(iter); 00400 int ndx = GET_INT_FROM_POINTER(value); 00401 00402 if(ndx < 0) 00403 ndx = -ndx + node->uniq_verts - 1; 00404 00405 node->vert_indices[ndx] = 00406 GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(iter)); 00407 } 00408 00409 BLI_ghashIterator_free(iter); 00410 00411 for(i = 0; i < totface; ++i) { 00412 MFace *f = bvh->faces + node->prim_indices[i]; 00413 int sides = f->v4 ? 4 : 3; 00414 00415 for(j = 0; j < sides; ++j) { 00416 if(node->face_vert_indices[i][j] < 0) 00417 node->face_vert_indices[i][j]= 00418 -node->face_vert_indices[i][j] + 00419 node->uniq_verts - 1; 00420 } 00421 } 00422 00423 if(!G.background) { 00424 node->draw_buffers = 00425 GPU_build_mesh_buffers(map, bvh->verts, bvh->faces, 00426 node->prim_indices, 00427 node->totprim, node->vert_indices, 00428 node->uniq_verts, 00429 node->uniq_verts + node->face_verts); 00430 } 00431 00432 node->flag |= PBVH_UpdateDrawBuffers; 00433 00434 BLI_ghash_free(map, NULL, NULL); 00435 } 00436 00437 static void build_grids_leaf_node(PBVH *bvh, PBVHNode *node) 00438 { 00439 if(!G.background) { 00440 node->draw_buffers = 00441 GPU_build_grid_buffers(bvh->grids, node->prim_indices, 00442 node->totprim, bvh->gridsize); 00443 } 00444 node->flag |= PBVH_UpdateDrawBuffers; 00445 } 00446 00447 /* Recursively build a node in the tree 00448 00449 vb is the voxel box around all of the primitives contained in 00450 this node. 00451 00452 cb is the bounding box around all the centroids of the primitives 00453 contained in this node 00454 00455 offset and start indicate a range in the array of primitive indices 00456 */ 00457 00458 static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, 00459 int offset, int count) 00460 { 00461 int i, axis, end; 00462 BB cb_backing; 00463 00464 /* Decide whether this is a leaf or not */ 00465 // XXX adapt leaf limit for grids 00466 if(count <= bvh->leaf_limit) { 00467 bvh->nodes[node_index].flag |= PBVH_Leaf; 00468 00469 bvh->nodes[node_index].prim_indices = bvh->prim_indices + offset; 00470 bvh->nodes[node_index].totprim = count; 00471 00472 /* Still need vb for searches */ 00473 BB_reset(&bvh->nodes[node_index].vb); 00474 for(i = offset + count - 1; i >= offset; --i) { 00475 BB_expand_with_bb(&bvh->nodes[node_index].vb, 00476 (BB*)(prim_bbc + 00477 bvh->prim_indices[i])); 00478 } 00479 00480 if(bvh->faces) 00481 build_mesh_leaf_node(bvh, bvh->nodes + node_index); 00482 else 00483 build_grids_leaf_node(bvh, bvh->nodes + node_index); 00484 bvh->nodes[node_index].orig_vb= bvh->nodes[node_index].vb; 00485 00486 /* Done with this subtree */ 00487 return; 00488 } 00489 else { 00490 BB_reset(&bvh->nodes[node_index].vb); 00491 bvh->nodes[node_index].children_offset = bvh->totnode; 00492 grow_nodes(bvh, bvh->totnode + 2); 00493 00494 if(!cb) { 00495 cb = &cb_backing; 00496 BB_reset(cb); 00497 for(i = offset + count - 1; i >= offset; --i) 00498 BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid); 00499 } 00500 } 00501 00502 axis = BB_widest_axis(cb); 00503 00504 for(i = offset + count - 1; i >= offset; --i) { 00505 BB_expand_with_bb(&bvh->nodes[node_index].vb, 00506 (BB*)(prim_bbc + bvh->prim_indices[i])); 00507 } 00508 00509 bvh->nodes[node_index].orig_vb= bvh->nodes[node_index].vb; 00510 00511 end = partition_indices(bvh->prim_indices, offset, offset + count - 1, 00512 axis, 00513 (cb->bmax[axis] + cb->bmin[axis]) * 0.5f, 00514 prim_bbc); 00515 check_partitioning(bvh->prim_indices, offset, offset + count - 1, 00516 axis, 00517 (cb->bmax[axis] + cb->bmin[axis]) * 0.5f, 00518 prim_bbc, end); 00519 00520 build_sub(bvh, bvh->nodes[node_index].children_offset, NULL, 00521 prim_bbc, offset, end - offset); 00522 build_sub(bvh, bvh->nodes[node_index].children_offset + 1, NULL, 00523 prim_bbc, end, offset + count - end); 00524 } 00525 00526 static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim) 00527 { 00528 int i; 00529 00530 if(totprim != bvh->totprim) { 00531 bvh->totprim = totprim; 00532 if(bvh->nodes) MEM_freeN(bvh->nodes); 00533 if(bvh->prim_indices) MEM_freeN(bvh->prim_indices); 00534 bvh->prim_indices = MEM_callocN(sizeof(int) * totprim, 00535 "bvh prim indices"); 00536 for(i = 0; i < totprim; ++i) 00537 bvh->prim_indices[i] = i; 00538 bvh->totnode = 0; 00539 if(bvh->node_mem_count < 100) { 00540 bvh->node_mem_count = 100; 00541 bvh->nodes = MEM_callocN(sizeof(PBVHNode) * 00542 bvh->node_mem_count, 00543 "bvh initial nodes"); 00544 } 00545 } 00546 00547 bvh->totnode = 1; 00548 build_sub(bvh, 0, cb, prim_bbc, 0, totprim); 00549 } 00550 00551 /* Do a full rebuild with on Mesh data structure */ 00552 void BLI_pbvh_build_mesh(PBVH *bvh, MFace *faces, MVert *verts, int totface, int totvert) 00553 { 00554 BBC *prim_bbc = NULL; 00555 BB cb; 00556 int i, j; 00557 00558 bvh->faces = faces; 00559 bvh->verts = verts; 00560 bvh->vert_bitmap = BLI_bitmap_new(totvert); 00561 bvh->totvert = totvert; 00562 bvh->leaf_limit = LEAF_LIMIT; 00563 00564 BB_reset(&cb); 00565 00566 /* For each face, store the AABB and the AABB centroid */ 00567 prim_bbc = MEM_mallocN(sizeof(BBC) * totface, "prim_bbc"); 00568 00569 for(i = 0; i < totface; ++i) { 00570 MFace *f = faces + i; 00571 const int sides = f->v4 ? 4 : 3; 00572 BBC *bbc = prim_bbc + i; 00573 00574 BB_reset((BB*)bbc); 00575 00576 for(j = 0; j < sides; ++j) 00577 BB_expand((BB*)bbc, verts[(&f->v1)[j]].co); 00578 00579 BBC_update_centroid(bbc); 00580 00581 BB_expand(&cb, bbc->bcentroid); 00582 } 00583 00584 if(totface) 00585 pbvh_build(bvh, &cb, prim_bbc, totface); 00586 00587 MEM_freeN(prim_bbc); 00588 MEM_freeN(bvh->vert_bitmap); 00589 } 00590 00591 /* Do a full rebuild with on Grids data structure */ 00592 void BLI_pbvh_build_grids(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj, 00593 int totgrid, int gridsize, void **gridfaces) 00594 { 00595 BBC *prim_bbc = NULL; 00596 BB cb; 00597 int i, j; 00598 00599 bvh->grids= grids; 00600 bvh->gridadj= gridadj; 00601 bvh->gridfaces= gridfaces; 00602 bvh->totgrid= totgrid; 00603 bvh->gridsize= gridsize; 00604 bvh->leaf_limit = MAX2(LEAF_LIMIT/((gridsize-1)*(gridsize-1)), 1); 00605 00606 BB_reset(&cb); 00607 00608 /* For each grid, store the AABB and the AABB centroid */ 00609 prim_bbc = MEM_mallocN(sizeof(BBC) * totgrid, "prim_bbc"); 00610 00611 for(i = 0; i < totgrid; ++i) { 00612 DMGridData *grid= grids[i]; 00613 BBC *bbc = prim_bbc + i; 00614 00615 BB_reset((BB*)bbc); 00616 00617 for(j = 0; j < gridsize*gridsize; ++j) 00618 BB_expand((BB*)bbc, grid[j].co); 00619 00620 BBC_update_centroid(bbc); 00621 00622 BB_expand(&cb, bbc->bcentroid); 00623 } 00624 00625 if(totgrid) 00626 pbvh_build(bvh, &cb, prim_bbc, totgrid); 00627 00628 MEM_freeN(prim_bbc); 00629 } 00630 00631 PBVH *BLI_pbvh_new(void) 00632 { 00633 PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh"); 00634 00635 return bvh; 00636 } 00637 00638 void BLI_pbvh_free(PBVH *bvh) 00639 { 00640 PBVHNode *node; 00641 int i; 00642 00643 for(i = 0; i < bvh->totnode; ++i) { 00644 node= &bvh->nodes[i]; 00645 00646 if(node->flag & PBVH_Leaf) { 00647 if(node->draw_buffers) 00648 GPU_free_buffers(node->draw_buffers); 00649 if(node->vert_indices) 00650 MEM_freeN(node->vert_indices); 00651 if(node->face_vert_indices) 00652 MEM_freeN(node->face_vert_indices); 00653 } 00654 } 00655 00656 if (bvh->deformed) { 00657 if (bvh->verts) { 00658 /* if pbvh was deformed, new memory was allocated for verts/faces -- free it */ 00659 00660 MEM_freeN(bvh->verts); 00661 MEM_freeN(bvh->faces); 00662 } 00663 } 00664 00665 MEM_freeN(bvh->nodes); 00666 MEM_freeN(bvh->prim_indices); 00667 MEM_freeN(bvh); 00668 } 00669 00670 static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BLI_pbvh_SearchCallback scb, void *search_data) 00671 { 00672 iter->bvh= bvh; 00673 iter->scb= scb; 00674 iter->search_data= search_data; 00675 00676 iter->stack= iter->stackfixed; 00677 iter->stackspace= STACK_FIXED_DEPTH; 00678 00679 iter->stack[0].node= bvh->nodes; 00680 iter->stack[0].revisiting= 0; 00681 iter->stacksize= 1; 00682 } 00683 00684 static void pbvh_iter_end(PBVHIter *iter) 00685 { 00686 if(iter->stackspace > STACK_FIXED_DEPTH) 00687 MEM_freeN(iter->stack); 00688 } 00689 00690 static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, int revisiting) 00691 { 00692 if(iter->stacksize == iter->stackspace) { 00693 PBVHStack *newstack; 00694 00695 iter->stackspace *= 2; 00696 newstack= MEM_callocN(sizeof(PBVHStack)*iter->stackspace, "PBVHStack"); 00697 memcpy(newstack, iter->stack, sizeof(PBVHStack)*iter->stacksize); 00698 00699 if(iter->stackspace > STACK_FIXED_DEPTH) 00700 MEM_freeN(iter->stack); 00701 iter->stack= newstack; 00702 } 00703 00704 iter->stack[iter->stacksize].node= node; 00705 iter->stack[iter->stacksize].revisiting= revisiting; 00706 iter->stacksize++; 00707 } 00708 00709 static PBVHNode *pbvh_iter_next(PBVHIter *iter) 00710 { 00711 PBVHNode *node; 00712 int revisiting; 00713 00714 /* purpose here is to traverse tree, visiting child nodes before their 00715 parents, this order is necessary for e.g. computing bounding boxes */ 00716 00717 while(iter->stacksize) { 00718 /* pop node */ 00719 iter->stacksize--; 00720 node= iter->stack[iter->stacksize].node; 00721 00722 /* on a mesh with no faces this can happen 00723 * can remove this check if we know meshes have at least 1 face */ 00724 if(node==NULL) 00725 return NULL; 00726 00727 revisiting= iter->stack[iter->stacksize].revisiting; 00728 00729 /* revisiting node already checked */ 00730 if(revisiting) 00731 return node; 00732 00733 if(iter->scb && !iter->scb(node, iter->search_data)) 00734 continue; /* don't traverse, outside of search zone */ 00735 00736 if(node->flag & PBVH_Leaf) { 00737 /* immediately hit leaf node */ 00738 return node; 00739 } 00740 else { 00741 /* come back later when children are done */ 00742 pbvh_stack_push(iter, node, 1); 00743 00744 /* push two child nodes on the stack */ 00745 pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset+1, 0); 00746 pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset, 0); 00747 } 00748 } 00749 00750 return NULL; 00751 } 00752 00753 static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter) 00754 { 00755 PBVHNode *node; 00756 00757 while(iter->stacksize) { 00758 /* pop node */ 00759 iter->stacksize--; 00760 node= iter->stack[iter->stacksize].node; 00761 00762 /* on a mesh with no faces this can happen 00763 * can remove this check if we know meshes have at least 1 face */ 00764 if(node==NULL) return NULL; 00765 00766 if(iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */ 00767 00768 if(node->flag & PBVH_Leaf) { 00769 /* immediately hit leaf node */ 00770 return node; 00771 } 00772 else { 00773 pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset+1, 0); 00774 pbvh_stack_push(iter, iter->bvh->nodes+node->children_offset, 0); 00775 } 00776 } 00777 00778 return NULL; 00779 } 00780 00781 void BLI_pbvh_search_gather(PBVH *bvh, 00782 BLI_pbvh_SearchCallback scb, void *search_data, 00783 PBVHNode ***r_array, int *r_tot) 00784 { 00785 PBVHIter iter; 00786 PBVHNode **array= NULL, **newarray, *node; 00787 int tot= 0, space= 0; 00788 00789 pbvh_iter_begin(&iter, bvh, scb, search_data); 00790 00791 while((node=pbvh_iter_next(&iter))) { 00792 if(node->flag & PBVH_Leaf) { 00793 if(tot == space) { 00794 /* resize array if needed */ 00795 space= (tot == 0)? 32: space*2; 00796 newarray= MEM_callocN(sizeof(PBVHNode)*space, "PBVHNodeSearch"); 00797 00798 if(array) { 00799 memcpy(newarray, array, sizeof(PBVHNode)*tot); 00800 MEM_freeN(array); 00801 } 00802 00803 array= newarray; 00804 } 00805 00806 array[tot]= node; 00807 tot++; 00808 } 00809 } 00810 00811 pbvh_iter_end(&iter); 00812 00813 if(tot == 0 && array) { 00814 MEM_freeN(array); 00815 array= NULL; 00816 } 00817 00818 *r_array= array; 00819 *r_tot= tot; 00820 } 00821 00822 void BLI_pbvh_search_callback(PBVH *bvh, 00823 BLI_pbvh_SearchCallback scb, void *search_data, 00824 BLI_pbvh_HitCallback hcb, void *hit_data) 00825 { 00826 PBVHIter iter; 00827 PBVHNode *node; 00828 00829 pbvh_iter_begin(&iter, bvh, scb, search_data); 00830 00831 while((node=pbvh_iter_next(&iter))) 00832 if (node->flag & PBVH_Leaf) 00833 hcb(node, hit_data); 00834 00835 pbvh_iter_end(&iter); 00836 } 00837 00838 typedef struct node_tree { 00839 PBVHNode* data; 00840 00841 struct node_tree* left; 00842 struct node_tree* right; 00843 } node_tree; 00844 00845 static void node_tree_insert(node_tree* tree, node_tree* new_node) 00846 { 00847 if (new_node->data->tmin < tree->data->tmin) { 00848 if (tree->left) { 00849 node_tree_insert(tree->left, new_node); 00850 } 00851 else { 00852 tree->left = new_node; 00853 } 00854 } 00855 else { 00856 if (tree->right) { 00857 node_tree_insert(tree->right, new_node); 00858 } 00859 else { 00860 tree->right = new_node; 00861 } 00862 } 00863 } 00864 00865 static void traverse_tree(node_tree* tree, BLI_pbvh_HitOccludedCallback hcb, void* hit_data, float* tmin) 00866 { 00867 if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin); 00868 00869 hcb(tree->data, hit_data, tmin); 00870 00871 if (tree->right) traverse_tree(tree->right, hcb, hit_data, tmin); 00872 } 00873 00874 static void free_tree(node_tree* tree) 00875 { 00876 if (tree->left) { 00877 free_tree(tree->left); 00878 tree->left = 0; 00879 } 00880 00881 if (tree->right) { 00882 free_tree(tree->right); 00883 tree->right = 0; 00884 } 00885 00886 free(tree); 00887 } 00888 00889 float BLI_pbvh_node_get_tmin(PBVHNode* node) 00890 { 00891 return node->tmin; 00892 } 00893 00894 static void BLI_pbvh_search_callback_occluded(PBVH *bvh, 00895 BLI_pbvh_SearchCallback scb, void *search_data, 00896 BLI_pbvh_HitOccludedCallback hcb, void *hit_data) 00897 { 00898 PBVHIter iter; 00899 PBVHNode *node; 00900 node_tree *tree = 0; 00901 00902 pbvh_iter_begin(&iter, bvh, scb, search_data); 00903 00904 while((node=pbvh_iter_next_occluded(&iter))) { 00905 if(node->flag & PBVH_Leaf) { 00906 node_tree* new_node = malloc(sizeof(node_tree)); 00907 00908 new_node->data = node; 00909 00910 new_node->left = NULL; 00911 new_node->right = NULL; 00912 00913 if (tree) { 00914 node_tree_insert(tree, new_node); 00915 } 00916 else { 00917 tree = new_node; 00918 } 00919 } 00920 } 00921 00922 pbvh_iter_end(&iter); 00923 00924 if (tree) { 00925 float tmin = FLT_MAX; 00926 traverse_tree(tree, hcb, hit_data, &tmin); 00927 free_tree(tree); 00928 } 00929 } 00930 00931 static int update_search_cb(PBVHNode *node, void *data_v) 00932 { 00933 int flag= GET_INT_FROM_POINTER(data_v); 00934 00935 if(node->flag & PBVH_Leaf) 00936 return (node->flag & flag); 00937 00938 return 1; 00939 } 00940 00941 static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, 00942 int totnode, float (*face_nors)[3]) 00943 { 00944 float (*vnor)[3]; 00945 int n; 00946 00947 if(bvh->grids) 00948 return; 00949 00950 /* could be per node to save some memory, but also means 00951 we have to store for each vertex which node it is in */ 00952 vnor= MEM_callocN(sizeof(float)*3*bvh->totvert, "bvh temp vnors"); 00953 00954 /* subtle assumptions: 00955 - We know that for all edited vertices, the nodes with faces 00956 adjacent to these vertices have been marked with PBVH_UpdateNormals. 00957 This is true because if the vertex is inside the brush radius, the 00958 bounding box of it's adjacent faces will be as well. 00959 - However this is only true for the vertices that have actually been 00960 edited, not for all vertices in the nodes marked for update, so we 00961 can only update vertices marked with ME_VERT_PBVH_UPDATE. 00962 */ 00963 00964 #pragma omp parallel for private(n) schedule(static) 00965 for(n = 0; n < totnode; n++) { 00966 PBVHNode *node= nodes[n]; 00967 00968 if((node->flag & PBVH_UpdateNormals)) { 00969 int i, j, totface, *faces; 00970 00971 faces= node->prim_indices; 00972 totface= node->totprim; 00973 00974 for(i = 0; i < totface; ++i) { 00975 MFace *f= bvh->faces + faces[i]; 00976 float fn[3]; 00977 unsigned int *fv = &f->v1; 00978 int sides= (f->v4)? 4: 3; 00979 00980 if(f->v4) 00981 normal_quad_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co, 00982 bvh->verts[f->v3].co, bvh->verts[f->v4].co); 00983 else 00984 normal_tri_v3(fn, bvh->verts[f->v1].co, bvh->verts[f->v2].co, 00985 bvh->verts[f->v3].co); 00986 00987 for(j = 0; j < sides; ++j) { 00988 int v= fv[j]; 00989 00990 if(bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) { 00991 /* this seems like it could be very slow but profile 00992 does not show this, so just leave it for now? */ 00993 #pragma omp atomic 00994 vnor[v][0] += fn[0]; 00995 #pragma omp atomic 00996 vnor[v][1] += fn[1]; 00997 #pragma omp atomic 00998 vnor[v][2] += fn[2]; 00999 } 01000 } 01001 01002 if(face_nors) 01003 copy_v3_v3(face_nors[faces[i]], fn); 01004 } 01005 } 01006 } 01007 01008 #pragma omp parallel for private(n) schedule(static) 01009 for(n = 0; n < totnode; n++) { 01010 PBVHNode *node= nodes[n]; 01011 01012 if(node->flag & PBVH_UpdateNormals) { 01013 int i, *verts, totvert; 01014 01015 verts= node->vert_indices; 01016 totvert= node->uniq_verts; 01017 01018 for(i = 0; i < totvert; ++i) { 01019 const int v = verts[i]; 01020 MVert *mvert= &bvh->verts[v]; 01021 01022 if(mvert->flag & ME_VERT_PBVH_UPDATE) { 01023 float no[3]; 01024 01025 copy_v3_v3(no, vnor[v]); 01026 normalize_v3(no); 01027 01028 mvert->no[0] = (short)(no[0]*32767.0f); 01029 mvert->no[1] = (short)(no[1]*32767.0f); 01030 mvert->no[2] = (short)(no[2]*32767.0f); 01031 01032 mvert->flag &= ~ME_VERT_PBVH_UPDATE; 01033 } 01034 } 01035 01036 node->flag &= ~PBVH_UpdateNormals; 01037 } 01038 } 01039 01040 MEM_freeN(vnor); 01041 } 01042 01043 static void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, 01044 int totnode, int flag) 01045 { 01046 int n; 01047 01048 /* update BB, redraw flag */ 01049 #pragma omp parallel for private(n) schedule(static) 01050 for(n = 0; n < totnode; n++) { 01051 PBVHNode *node= nodes[n]; 01052 01053 if((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) 01054 /* don't clear flag yet, leave it for flushing later */ 01055 update_node_vb(bvh, node); 01056 01057 if((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) 01058 node->orig_vb= node->vb; 01059 01060 if((flag & PBVH_UpdateRedraw) && (node->flag & PBVH_UpdateRedraw)) 01061 node->flag &= ~PBVH_UpdateRedraw; 01062 } 01063 } 01064 01065 static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int smooth) 01066 { 01067 PBVHNode *node; 01068 int n; 01069 01070 /* can't be done in parallel with OpenGL */ 01071 for(n = 0; n < totnode; n++) { 01072 node= nodes[n]; 01073 01074 if(node->flag & PBVH_UpdateDrawBuffers) { 01075 if(bvh->grids) { 01076 GPU_update_grid_buffers(node->draw_buffers, 01077 bvh->grids, 01078 node->prim_indices, 01079 node->totprim, 01080 bvh->gridsize, 01081 smooth); 01082 } 01083 else { 01084 GPU_update_mesh_buffers(node->draw_buffers, 01085 bvh->verts, 01086 node->vert_indices, 01087 node->uniq_verts + 01088 node->face_verts); 01089 } 01090 01091 node->flag &= ~PBVH_UpdateDrawBuffers; 01092 } 01093 } 01094 } 01095 01096 static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) 01097 { 01098 int update= 0; 01099 01100 /* difficult to multithread well, we just do single threaded recursive */ 01101 if(node->flag & PBVH_Leaf) { 01102 if(flag & PBVH_UpdateBB) { 01103 update |= (node->flag & PBVH_UpdateBB); 01104 node->flag &= ~PBVH_UpdateBB; 01105 } 01106 01107 if(flag & PBVH_UpdateOriginalBB) { 01108 update |= (node->flag & PBVH_UpdateOriginalBB); 01109 node->flag &= ~PBVH_UpdateOriginalBB; 01110 } 01111 01112 return update; 01113 } 01114 else { 01115 update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset, flag); 01116 update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset + 1, flag); 01117 01118 if(update & PBVH_UpdateBB) 01119 update_node_vb(bvh, node); 01120 if(update & PBVH_UpdateOriginalBB) 01121 node->orig_vb= node->vb; 01122 } 01123 01124 return update; 01125 } 01126 01127 void BLI_pbvh_update(PBVH *bvh, int flag, float (*face_nors)[3]) 01128 { 01129 PBVHNode **nodes; 01130 int totnode; 01131 01132 BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(flag), 01133 &nodes, &totnode); 01134 01135 if(flag & PBVH_UpdateNormals) 01136 pbvh_update_normals(bvh, nodes, totnode, face_nors); 01137 01138 if(flag & (PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw)) 01139 pbvh_update_BB_redraw(bvh, nodes, totnode, flag); 01140 01141 if(flag & (PBVH_UpdateBB|PBVH_UpdateOriginalBB)) 01142 pbvh_flush_bb(bvh, bvh->nodes, flag); 01143 01144 if(nodes) MEM_freeN(nodes); 01145 } 01146 01147 void BLI_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) 01148 { 01149 PBVHIter iter; 01150 PBVHNode *node; 01151 BB bb; 01152 01153 BB_reset(&bb); 01154 01155 pbvh_iter_begin(&iter, bvh, NULL, NULL); 01156 01157 while((node=pbvh_iter_next(&iter))) 01158 if(node->flag & PBVH_UpdateRedraw) 01159 BB_expand_with_bb(&bb, &node->vb); 01160 01161 pbvh_iter_end(&iter); 01162 01163 copy_v3_v3(bb_min, bb.bmin); 01164 copy_v3_v3(bb_max, bb.bmax); 01165 } 01166 01167 void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface) 01168 { 01169 PBVHIter iter; 01170 PBVHNode *node; 01171 GHashIterator *hiter; 01172 GHash *map; 01173 void *face, **faces; 01174 unsigned i; 01175 int tot; 01176 01177 map = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "pbvh_get_grid_updates gh"); 01178 01179 pbvh_iter_begin(&iter, bvh, NULL, NULL); 01180 01181 while((node=pbvh_iter_next(&iter))) { 01182 if(node->flag & PBVH_UpdateNormals) { 01183 for(i = 0; i < node->totprim; ++i) { 01184 face= bvh->gridfaces[node->prim_indices[i]]; 01185 if(!BLI_ghash_lookup(map, face)) 01186 BLI_ghash_insert(map, face, face); 01187 } 01188 01189 if(clear) 01190 node->flag &= ~PBVH_UpdateNormals; 01191 } 01192 } 01193 01194 pbvh_iter_end(&iter); 01195 01196 tot= BLI_ghash_size(map); 01197 if(tot == 0) { 01198 *totface= 0; 01199 *gridfaces= NULL; 01200 BLI_ghash_free(map, NULL, NULL); 01201 return; 01202 } 01203 01204 faces= MEM_callocN(sizeof(void*)*tot, "PBVH Grid Faces"); 01205 01206 for(hiter = BLI_ghashIterator_new(map), i = 0; 01207 !BLI_ghashIterator_isDone(hiter); 01208 BLI_ghashIterator_step(hiter), ++i) 01209 faces[i]= BLI_ghashIterator_getKey(hiter); 01210 01211 BLI_ghashIterator_free(hiter); 01212 01213 BLI_ghash_free(map, NULL, NULL); 01214 01215 *totface= tot; 01216 *gridfaces= faces; 01217 } 01218 01219 /***************************** Node Access ***********************************/ 01220 01221 void BLI_pbvh_node_mark_update(PBVHNode *node) 01222 { 01223 node->flag |= PBVH_UpdateNormals|PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateDrawBuffers|PBVH_UpdateRedraw; 01224 } 01225 01226 void BLI_pbvh_node_get_verts(PBVH *bvh, PBVHNode *node, int **vert_indices, MVert **verts) 01227 { 01228 if(vert_indices) *vert_indices= node->vert_indices; 01229 if(verts) *verts= bvh->verts; 01230 } 01231 01232 void BLI_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *totvert) 01233 { 01234 if(bvh->grids) { 01235 const int tot= node->totprim*bvh->gridsize*bvh->gridsize; 01236 if(totvert) *totvert= tot; 01237 if(uniquevert) *uniquevert= tot; 01238 } 01239 else { 01240 if(totvert) *totvert= node->uniq_verts + node->face_verts; 01241 if(uniquevert) *uniquevert= node->uniq_verts; 01242 } 01243 } 01244 01245 void BLI_pbvh_node_get_grids(PBVH *bvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, DMGridData ***griddata, DMGridAdjacency **gridadj) 01246 { 01247 if(bvh->grids) { 01248 if(grid_indices) *grid_indices= node->prim_indices; 01249 if(totgrid) *totgrid= node->totprim; 01250 if(maxgrid) *maxgrid= bvh->totgrid; 01251 if(gridsize) *gridsize= bvh->gridsize; 01252 if(griddata) *griddata= bvh->grids; 01253 if(gridadj) *gridadj= bvh->gridadj; 01254 } 01255 else { 01256 if(grid_indices) *grid_indices= NULL; 01257 if(totgrid) *totgrid= 0; 01258 if(maxgrid) *maxgrid= 0; 01259 if(gridsize) *gridsize= 0; 01260 if(griddata) *griddata= NULL; 01261 if(gridadj) *gridadj= NULL; 01262 } 01263 } 01264 01265 void BLI_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]) 01266 { 01267 copy_v3_v3(bb_min, node->vb.bmin); 01268 copy_v3_v3(bb_max, node->vb.bmax); 01269 } 01270 01271 void BLI_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]) 01272 { 01273 copy_v3_v3(bb_min, node->orig_vb.bmin); 01274 copy_v3_v3(bb_max, node->orig_vb.bmax); 01275 } 01276 01277 void BLI_pbvh_node_get_proxies(PBVHNode* node, PBVHProxyNode** proxies, int* proxy_count) 01278 { 01279 if (node->proxy_count > 0) { 01280 if (proxies) *proxies = node->proxies; 01281 if (proxy_count) *proxy_count = node->proxy_count; 01282 } 01283 else { 01284 if (proxies) *proxies = 0; 01285 if (proxy_count) *proxy_count = 0; 01286 } 01287 } 01288 01289 /********************************* Raycast ***********************************/ 01290 01291 typedef struct { 01292 /* Ray */ 01293 float start[3]; 01294 int sign[3]; 01295 float inv_dir[3]; 01296 int original; 01297 } RaycastData; 01298 01299 /* Adapted from here: http://www.gamedev.net/community/forums/topic.asp?topic_id=459973 */ 01300 static int ray_aabb_intersect(PBVHNode *node, void *data_v) 01301 { 01302 RaycastData *ray = data_v; 01303 float bbox[2][3]; 01304 float tmin, tmax, tymin, tymax, tzmin, tzmax; 01305 01306 if(ray->original) 01307 BLI_pbvh_node_get_original_BB(node, bbox[0], bbox[1]); 01308 else 01309 BLI_pbvh_node_get_BB(node, bbox[0], bbox[1]); 01310 01311 tmin = (bbox[ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0]; 01312 tmax = (bbox[1-ray->sign[0]][0] - ray->start[0]) * ray->inv_dir[0]; 01313 01314 tymin = (bbox[ray->sign[1]][1] - ray->start[1]) * ray->inv_dir[1]; 01315 tymax = (bbox[1-ray->sign[1]][1] - ray->start[1]) * ray->inv_dir[1]; 01316 01317 if((tmin > tymax) || (tymin > tmax)) 01318 return 0; 01319 01320 if(tymin > tmin) 01321 tmin = tymin; 01322 01323 if(tymax < tmax) 01324 tmax = tymax; 01325 01326 tzmin = (bbox[ray->sign[2]][2] - ray->start[2]) * ray->inv_dir[2]; 01327 tzmax = (bbox[1-ray->sign[2]][2] - ray->start[2]) * ray->inv_dir[2]; 01328 01329 if((tmin > tzmax) || (tzmin > tmax)) 01330 return 0; 01331 01332 if(tzmin > tmin) 01333 tmin = tzmin; 01334 01335 // XXX jwilkins: tmax does not need to be updated since we don't use it 01336 // keeping this here for future reference 01337 //if(tzmax < tmax) tmax = tzmax; 01338 01339 node->tmin = tmin; 01340 01341 return 1; 01342 } 01343 01344 void BLI_pbvh_raycast(PBVH *bvh, BLI_pbvh_HitOccludedCallback cb, void *data, 01345 float ray_start[3], float ray_normal[3], int original) 01346 { 01347 RaycastData rcd; 01348 01349 copy_v3_v3(rcd.start, ray_start); 01350 rcd.inv_dir[0] = 1.0f / ray_normal[0]; 01351 rcd.inv_dir[1] = 1.0f / ray_normal[1]; 01352 rcd.inv_dir[2] = 1.0f / ray_normal[2]; 01353 rcd.sign[0] = rcd.inv_dir[0] < 0; 01354 rcd.sign[1] = rcd.inv_dir[1] < 0; 01355 rcd.sign[2] = rcd.inv_dir[2] < 0; 01356 rcd.original = original; 01357 01358 BLI_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data); 01359 } 01360 01361 static int ray_face_intersection(float ray_start[3], float ray_normal[3], 01362 float *t0, float *t1, float *t2, float *t3, 01363 float *fdist) 01364 { 01365 float dist; 01366 01367 if ((isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t1, t2, &dist, NULL, 0.1f) && dist < *fdist) || 01368 (t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist)) 01369 { 01370 *fdist = dist; 01371 return 1; 01372 } 01373 else { 01374 return 0; 01375 } 01376 } 01377 01378 int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], 01379 float ray_start[3], float ray_normal[3], float *dist) 01380 { 01381 int hit= 0; 01382 01383 if(bvh->faces) { 01384 MVert *vert = bvh->verts; 01385 int *faces= node->prim_indices; 01386 int totface= node->totprim; 01387 int i; 01388 01389 for(i = 0; i < totface; ++i) { 01390 MFace *f = bvh->faces + faces[i]; 01391 int *face_verts = node->face_vert_indices[i]; 01392 01393 if(origco) { 01394 /* intersect with backuped original coordinates */ 01395 hit |= ray_face_intersection(ray_start, ray_normal, 01396 origco[face_verts[0]], 01397 origco[face_verts[1]], 01398 origco[face_verts[2]], 01399 f->v4? origco[face_verts[3]]: NULL, 01400 dist); 01401 } 01402 else { 01403 /* intersect with current coordinates */ 01404 hit |= ray_face_intersection(ray_start, ray_normal, 01405 vert[f->v1].co, 01406 vert[f->v2].co, 01407 vert[f->v3].co, 01408 f->v4 ? vert[f->v4].co : NULL, 01409 dist); 01410 } 01411 } 01412 } 01413 else { 01414 int totgrid= node->totprim; 01415 int gridsize= bvh->gridsize; 01416 int i, x, y; 01417 01418 for(i = 0; i < totgrid; ++i) { 01419 DMGridData *grid= bvh->grids[node->prim_indices[i]]; 01420 if (!grid) 01421 continue; 01422 01423 for(y = 0; y < gridsize-1; ++y) { 01424 for(x = 0; x < gridsize-1; ++x) { 01425 if(origco) { 01426 hit |= ray_face_intersection(ray_start, ray_normal, 01427 origco[y*gridsize + x], 01428 origco[y*gridsize + x+1], 01429 origco[(y+1)*gridsize + x+1], 01430 origco[(y+1)*gridsize + x], 01431 dist); 01432 } 01433 else { 01434 hit |= ray_face_intersection(ray_start, ray_normal, 01435 grid[y*gridsize + x].co, 01436 grid[y*gridsize + x+1].co, 01437 grid[(y+1)*gridsize + x+1].co, 01438 grid[(y+1)*gridsize + x].co, 01439 dist); 01440 } 01441 } 01442 } 01443 01444 if(origco) 01445 origco += gridsize*gridsize; 01446 } 01447 } 01448 01449 return hit; 01450 } 01451 01452 //#include <GL/glew.h> 01453 01454 void BLI_pbvh_node_draw(PBVHNode *node, void *UNUSED(data)) 01455 { 01456 #if 0 01457 /* XXX: Just some quick code to show leaf nodes in different colors */ 01458 float col[3]; int i; 01459 01460 if(0) { //is_partial) { 01461 col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6; 01462 } 01463 else { 01464 srand((long long)node); 01465 for(i = 0; i < 3; ++i) 01466 col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7; 01467 } 01468 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); 01469 01470 glColor3f(1, 0, 0); 01471 #endif 01472 GPU_draw_buffers(node->draw_buffers); 01473 } 01474 01475 /* Adapted from: 01476 http://www.gamedev.net/community/forums/topic.asp?topic_id=512123 01477 Returns true if the AABB is at least partially within the frustum 01478 (ok, not a real frustum), false otherwise. 01479 */ 01480 int BLI_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data) 01481 { 01482 float (*planes)[4] = data; 01483 int i, axis; 01484 float vmin[3] /*, vmax[3]*/, bb_min[3], bb_max[3]; 01485 01486 BLI_pbvh_node_get_BB(node, bb_min, bb_max); 01487 01488 for(i = 0; i < 4; ++i) { 01489 for(axis = 0; axis < 3; ++axis) { 01490 if(planes[i][axis] > 0) { 01491 vmin[axis] = bb_min[axis]; 01492 /*vmax[axis] = bb_max[axis];*/ /*UNUSED*/ 01493 } 01494 else { 01495 vmin[axis] = bb_max[axis]; 01496 /*vmax[axis] = bb_min[axis];*/ /*UNUSED*/ 01497 } 01498 } 01499 01500 if(dot_v3v3(planes[i], vmin) + planes[i][3] > 0) 01501 return 0; 01502 } 01503 01504 return 1; 01505 } 01506 01507 void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], int smooth) 01508 { 01509 PBVHNode **nodes; 01510 int totnode; 01511 01512 BLI_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals|PBVH_UpdateDrawBuffers), 01513 &nodes, &totnode); 01514 01515 pbvh_update_normals(bvh, nodes, totnode, face_nors); 01516 pbvh_update_draw_buffers(bvh, nodes, totnode, smooth); 01517 01518 if(nodes) MEM_freeN(nodes); 01519 01520 if(planes) { 01521 BLI_pbvh_search_callback(bvh, BLI_pbvh_node_planes_contain_AABB, 01522 planes, BLI_pbvh_node_draw, NULL); 01523 } 01524 else { 01525 BLI_pbvh_search_callback(bvh, NULL, NULL, BLI_pbvh_node_draw, NULL); 01526 } 01527 } 01528 01529 void BLI_pbvh_grids_update(PBVH *bvh, DMGridData **grids, DMGridAdjacency *gridadj, void **gridfaces) 01530 { 01531 bvh->grids= grids; 01532 bvh->gridadj= gridadj; 01533 bvh->gridfaces= gridfaces; 01534 } 01535 01536 float (*BLI_pbvh_get_vertCos(PBVH *pbvh))[3] 01537 { 01538 int a; 01539 float (*vertCos)[3]= NULL; 01540 01541 if (pbvh->verts) { 01542 float *co; 01543 MVert *mvert= pbvh->verts; 01544 01545 vertCos= MEM_callocN(3*pbvh->totvert*sizeof(float), "BLI_pbvh_get_vertCoords"); 01546 co= (float*)vertCos; 01547 01548 for (a= 0; a<pbvh->totvert; a++, mvert++, co+= 3) { 01549 copy_v3_v3(co, mvert->co); 01550 } 01551 } 01552 01553 return vertCos; 01554 } 01555 01556 void BLI_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3]) 01557 { 01558 int a; 01559 01560 if (!pbvh->deformed) { 01561 if (pbvh->verts) { 01562 /* if pbvh is not already deformed, verts/faces points to the */ 01563 /* original data and applying new coords to this arrays would lead to */ 01564 /* unneeded deformation -- duplicate verts/faces to avoid this */ 01565 01566 pbvh->verts= MEM_dupallocN(pbvh->verts); 01567 pbvh->faces= MEM_dupallocN(pbvh->faces); 01568 01569 pbvh->deformed= 1; 01570 } 01571 } 01572 01573 if (pbvh->verts) { 01574 MVert *mvert= pbvh->verts; 01575 /* copy new verts coords */ 01576 for (a= 0; a < pbvh->totvert; ++a, ++mvert) { 01577 copy_v3_v3(mvert->co, vertCos[a]); 01578 mvert->flag |= ME_VERT_PBVH_UPDATE; 01579 } 01580 01581 /* coordinates are new -- normals should also be updated */ 01582 mesh_calc_normals(pbvh->verts, pbvh->totvert, pbvh->faces, pbvh->totprim, NULL); 01583 01584 for (a= 0; a < pbvh->totnode; ++a) 01585 BLI_pbvh_node_mark_update(&pbvh->nodes[a]); 01586 01587 BLI_pbvh_update(pbvh, PBVH_UpdateBB, NULL); 01588 BLI_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL); 01589 01590 } 01591 } 01592 01593 int BLI_pbvh_isDeformed(PBVH *pbvh) 01594 { 01595 return pbvh->deformed; 01596 } 01597 /* Proxies */ 01598 01599 PBVHProxyNode* BLI_pbvh_node_add_proxy(PBVH* bvh, PBVHNode* node) 01600 { 01601 int index, totverts; 01602 01603 #pragma omp critical 01604 { 01605 01606 index = node->proxy_count; 01607 01608 node->proxy_count++; 01609 01610 if (node->proxies) 01611 node->proxies= MEM_reallocN(node->proxies, node->proxy_count*sizeof(PBVHProxyNode)); 01612 else 01613 node->proxies= MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy"); 01614 01615 if (bvh->grids) 01616 totverts = node->totprim*bvh->gridsize*bvh->gridsize; 01617 else 01618 totverts = node->uniq_verts; 01619 01620 node->proxies[index].co= MEM_callocN(sizeof(float[3])*totverts, "PBVHNodeProxy.co"); 01621 } 01622 01623 return node->proxies + index; 01624 } 01625 01626 void BLI_pbvh_node_free_proxies(PBVHNode* node) 01627 { 01628 #pragma omp critical 01629 { 01630 int p; 01631 01632 for (p= 0; p < node->proxy_count; p++) { 01633 MEM_freeN(node->proxies[p].co); 01634 node->proxies[p].co= 0; 01635 } 01636 01637 MEM_freeN(node->proxies); 01638 node->proxies = 0; 01639 01640 node->proxy_count= 0; 01641 } 01642 } 01643 01644 void BLI_pbvh_gather_proxies(PBVH* pbvh, PBVHNode*** r_array, int* r_tot) 01645 { 01646 PBVHNode **array= NULL, **newarray, *node; 01647 int tot= 0, space= 0; 01648 int n; 01649 01650 for (n= 0; n < pbvh->totnode; n++) { 01651 node = pbvh->nodes + n; 01652 01653 if(node->proxy_count > 0) { 01654 if(tot == space) { 01655 /* resize array if needed */ 01656 space= (tot == 0)? 32: space*2; 01657 newarray= MEM_callocN(sizeof(PBVHNode)*space, "BLI_pbvh_gather_proxies"); 01658 01659 if (array) { 01660 memcpy(newarray, array, sizeof(PBVHNode)*tot); 01661 MEM_freeN(array); 01662 } 01663 01664 array= newarray; 01665 } 01666 01667 array[tot]= node; 01668 tot++; 01669 } 01670 } 01671 01672 if(tot == 0 && array) { 01673 MEM_freeN(array); 01674 array= NULL; 01675 } 01676 01677 *r_array= array; 01678 *r_tot= tot; 01679 }