/* * Recursively builds the BVH starting at the given node with the given * first and last primitive indices (in bag). */ size_t BVH4::recursive_build(size_t parent, size_t first_prim, size_t last_prim) { // Allocate the node const size_t me = build_nodes.size(); build_nodes.push_back(BuildNode()); build_nodes[me].flags = 0; build_nodes[me].parent_index = parent; if (first_prim == last_prim) { // Leaf node build_nodes[me].flags |= IS_LEAF; build_nodes[me].data = prim_bag[first_prim].data; // Copy bounding boxes build_nodes[me].bbox_index = build_bboxes.size(); build_nodes[me].ts = prim_bag[first_prim].data->bounds().size(); for (size_t i = 0; i < build_nodes[me].ts; i++) build_bboxes.push_back(prim_bag[first_prim].data->bounds()[i]); } else { // Not a leaf node // Create child nodes uint32_t split_index = split_primitives(first_prim, last_prim); const size_t child1i = recursive_build(me, first_prim, split_index); const size_t child2i = recursive_build(me, split_index+1, last_prim); build_nodes[me].child_index = child2i; // Calculate bounds build_nodes[me].bbox_index = build_bboxes.size(); // If both children have same number of time samples if (build_nodes[child1i].ts == build_nodes[child2i].ts) { build_nodes[me].ts = build_nodes[child1i].ts; // Copy merged bounding boxes for (size_t i = 0; i < build_nodes[me].ts; i++) { build_bboxes.push_back(build_bboxes[build_nodes[child1i].bbox_index+i]); build_bboxes.back().merge_with(build_bboxes[build_nodes[child2i].bbox_index+i]); } } // If children have different number of time samples else { build_nodes[me].ts = 1; // Merge children's bboxes to get our bbox build_bboxes.push_back(build_bboxes[build_nodes[child1i].bbox_index]); for (size_t i = 1; i < build_nodes[child1i].ts; i++) build_bboxes.back().merge_with(build_bboxes[build_nodes[child1i].bbox_index+i]); for (size_t i = 0; i < build_nodes[child2i].ts; i++) build_bboxes.back().merge_with(build_bboxes[build_nodes[child2i].bbox_index+i]); } } return me; }
result_type operator() (conditional_defn_node const& conditional) { for(auto const& comp : conditional.components_) { recursive_build(g_, comp.nd, conditional, nd_map_); } if(conditional.default_) { recursive_build(g_, conditional.default_, conditional, nd_map_); } }
size_t LightTree::recursive_build(std::vector<LightTree::BuildNode>::iterator start, std::vector<LightTree::BuildNode>::iterator end) { // Allocate the node const size_t me = nodes.size(); nodes.push_back(Node()); if ((start + 1) == end) { // Leaf node const Instance& instance = assembly->instances[start->instance_index]; nodes[me].is_leaf = true; nodes[me].instance_index = start->instance_index; // Get bounds if (instance.type == Instance::OBJECT) { nodes[me].bounds = assembly->instance_bounds(start->instance_index); } else if (instance.type == Instance::ASSEMBLY) { const Assembly* assmb = assembly->assemblies[instance.data_index].get(); if (instance.transform_count > 0) { auto xstart = assembly->xforms.cbegin() + instance.transform_index; auto xend = xstart + instance.transform_count; nodes[me].bounds = transform_from(assmb->light_accel.bounds(), xstart, xend); } else { nodes[me].bounds = assmb->light_accel.bounds(); } } // Copy energy nodes[me].energy = start->energy; } else { // Not a leaf node nodes[me].is_leaf = false; // Create child nodes auto split_itr = split_lights(start, end); const size_t c1 = recursive_build(start, split_itr); const size_t c2 = recursive_build(split_itr, end); nodes[me].index1 = c1; nodes[me].index2 = c2; // Calculate bounds nodes[me].bounds = merge(nodes[c1].bounds, nodes[c2].bounds); // Calculate energy nodes[me].energy = nodes[c1].energy + nodes[c2].energy; } return me; }
result_type operator() (composite_defn_node const& composite) { auto children = composite.children(); for(auto const& c_dn : children) { recursive_build(g_, c_dn.second, composite, nd_map_); } }
bool randomize() override { if (!built_) { gen_ = std::make_shared<Generator>(); recursive_build(*gen_); built_ = true; } return gen_->nextCov(); }
bool randomize_with(Exprs... exprs) { // TODO Generator caching rand_with_gen_ = std::make_shared<Generator>(); recursive_build(*rand_with_gen_); expression_list list(exprs...); for (auto e : list) (*rand_with_gen_)(e); return rand_with_gen_->next(); }
void LightTree::build(const Assembly& assembly_) { assembly = &assembly_; // Populate the build nodes for (size_t i = 0; i < assembly->instances.size(); ++i) { const auto& instance = assembly->instances[i]; // Shorthand // If it's an object if (instance.type == Instance::OBJECT) { const Object* obj = assembly->objects[instance.data_index].get(); // Shorthand if (obj->total_emitted_color().energy() > 0.0f) { build_nodes.push_back(BuildNode()); build_nodes.back().instance_index = i; build_nodes.back().bbox = assembly->instance_bounds_at(0.5f, i); build_nodes.back().center = build_nodes.back().bbox.center(); const Vec3 scale = assembly->instance_xform_at(0.5f, i).get_inv_scale(); const float surface_scale = ((scale[0]*scale[1]) + (scale[0]*scale[2]) + (scale[1]*scale[2])) * 0.33333333f; build_nodes.back().energy = obj->total_emitted_color().energy() / surface_scale; ++total_lights; } } // If it's an assembly else if (instance.type == Instance::ASSEMBLY) { const Assembly* asmb = assembly->assemblies[instance.data_index].get(); // Shorthand const auto count = asmb->light_accel.light_count(); const float energy = asmb->light_accel.total_emitted_color().energy(); if (count > 0 && energy > 0.0f) { build_nodes.push_back(BuildNode()); build_nodes.back().instance_index = i; if (instance.transform_count > 0) { auto xstart = assembly->xforms.cbegin() + instance.transform_index; auto xend = xstart + instance.transform_count; build_nodes.back().bbox = lerp_seq(0.5f, asmb->light_accel.bounds()).inverse_transformed(lerp_seq(0.5f, xstart, xend)); } else { build_nodes.back().bbox = lerp_seq(0.5f, asmb->light_accel.bounds()); } build_nodes.back().center = build_nodes.back().bbox.center(); const Vec3 scale = assembly->instance_xform_at(0.5f, i).get_inv_scale(); const float surface_scale = ((scale[0]*scale[1]) + (scale[0]*scale[2]) + (scale[1]*scale[2])) * 0.33333333f; build_nodes.back().energy = energy / surface_scale; total_lights += count; } } } if (build_nodes.size() > 0) { recursive_build(build_nodes.begin(), build_nodes.end()); bounds_ = nodes[0].bounds; total_energy = nodes[0].energy; } else { bounds_.clear(); bounds_.emplace_back(BBox()); } }
// TODO: Currently this includes child->parent dependencies. defn_dep_graph build_defn_dependency_graph(defn_node dn) { defn_dep_graph g; if(!dn) { return g; } defn_build_node_map_t nd_map; recursive_build(g, dn, nd_map); return g; }
defn_dep_graph build_defn_dependency_graph(defn_node hierarchy_root, defn_node dep_root) { defn_dep_graph g; if(!hierarchy_root || !dep_root) { return g; } // Build up the complete dependency graph defn_build_node_map_t nd_map; recursive_build(g, hierarchy_root, defn_node{}, nd_map); // And then get the subgraph of nodes dependent on nref dependent_upon(g, dep_root); return g; }
bool BVH4::finalize() { if (prim_bag.size() == 0) return true; // Build BVH recursive_build(0, 0, prim_bag.size()-1); // Pack BVH into more efficient form pack(); // Empty the temporary build sets prim_bag.clear(); build_nodes.clear(); build_bboxes.clear(); return true; }
result_type operator() (list_defn_node const& list) { auto entry_dn = list.entrydefn(); recursive_build(g_, entry_dn, list, nd_map_); }