BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int *result) { int j; unsigned int total = 0; BVHTreeOverlap *overlap = NULL, *to = NULL; BVHOverlapData **data; /* check for compatibility of both trees (can't compare 14-DOP with 18-DOP) */ if ((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18)) return NULL; /* fast check root nodes for collision before doing big splitting + traversal */ if (!tree_overlap(tree1->nodes[tree1->totleaf], tree2->nodes[tree2->totleaf], min_axis(tree1->start_axis, tree2->start_axis), min_axis(tree1->stop_axis, tree2->stop_axis))) { return NULL; } data = MEM_callocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star"); for (j = 0; j < tree1->tree_type; j++) { data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); /* init BVHOverlapData */ data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * max_ii(tree1->totleaf, tree2->totleaf)); data[j]->tree1 = tree1; data[j]->tree2 = tree2; data[j]->max_overlap = max_ii(tree1->totleaf, tree2->totleaf); data[j]->i = 0; data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis); data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); } #pragma omp parallel for private(j) schedule(static) for (j = 0; j < MIN2(tree1->tree_type, tree1->nodes[tree1->totleaf]->totnode); j++) { traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]); } for (j = 0; j < tree1->tree_type; j++) total += data[j]->i; to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); for (j = 0; j < tree1->tree_type; j++) { memcpy(to, data[j]->overlap, data[j]->i * sizeof(BVHTreeOverlap)); to += data[j]->i; } for (j = 0; j < tree1->tree_type; j++) { free(data[j]->overlap); MEM_freeN(data[j]); } MEM_freeN(data); (*result) = total; return overlap; }
static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) { int j; if (tree_overlap(node1, node2, data->start_axis, data->stop_axis)) { // check if node1 is a leaf if (!node1->totnode) { // check if node2 is a leaf if (!node2->totnode) { if (node1 == node2) { return; } if (data->i >= data->max_overlap) { // try to make alloc'ed memory bigger data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2); if (!data->overlap) { printf("Out of Memory in traverse\n"); return; } data->max_overlap *= 2; } // both leafs, insert overlap! data->overlap[data->i].indexA = node1->index; data->overlap[data->i].indexB = node2->index; data->i++; } else { for (j = 0; j < data->tree2->tree_type; j++) { if (node2->children[j]) traverse(data, node1, node2->children[j]); } } } else { for (j = 0; j < data->tree2->tree_type; j++) { if (node1->children[j]) traverse(data, node1->children[j], node2); } } } return; }