void BVH::build(Progress& progress) { progress.set_substatus("Building BVH"); /* build nodes */ BVHBuild bvh_build(objects, pack.prim_type, pack.prim_index, pack.prim_object, params, progress); BVHNode *root = bvh_build.run(); if(progress.get_cancel()) { if(root) root->deleteSubtree(); return; } /* pack triangles */ progress.set_substatus("Packing BVH triangles and strands"); pack_primitives(); if(progress.get_cancel()) { root->deleteSubtree(); return; } /* pack nodes */ progress.set_substatus("Packing BVH nodes"); pack_nodes(root); /* free build nodes */ root->deleteSubtree(); }
BVHNode* BVHBuild::run() { BVHRange root; /* add references */ add_references(root); if(progress.get_cancel()) return NULL; /* init spatial splits */ if(params.top_level) /* todo: get rid of this */ params.use_spatial_split = false; spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha; spatial_right_bounds.clear(); spatial_right_bounds.resize(max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1); /* init progress updates */ progress_start_time = time_dt(); progress_count = 0; progress_total = references.size(); progress_original_total = progress_total; prim_segment.resize(references.size()); prim_index.resize(references.size()); prim_object.resize(references.size()); /* build recursively */ BVHNode *rootnode; if(params.use_spatial_split) { /* singlethreaded spatial split build */ rootnode = build_node(root, 0); } else { /* multithreaded binning build */ BVHObjectBinning rootbin(root, (references.size())? &references[0]: NULL); rootnode = build_node(rootbin, 0); task_pool.wait_work(); } /* delete if we canceled */ if(rootnode) { if(progress.get_cancel()) { rootnode->deleteSubtree(); rootnode = NULL; } else if(!params.use_spatial_split) { /*rotate(rootnode, 4, 5);*/ rootnode->update_visibility(); } } return rootnode; }