Exemple #1
0
	void build_recursive(Node * node, uint32_t depth, std::vector<std::shared_ptr<Traceable>> & objects)
	{
		Bounds3D nodeBounds = objects[0]->world_bounds();
		for (size_t i = 0; i < objects.size(); i++)
		{
			nodeBounds = nodeBounds.add(objects[i]->world_bounds());
		}
		node->bounds = nodeBounds;

		// Recursion limit was reached, create a new leaf
		if (objects.size() <= leafThreshold)
		{
			node->data.insert(node->data.end(), objects.begin(), objects.end());
			return;
		}

		// Split the node based on its longest axis
		node->axis = nodeBounds.maximum_extent();

		const size_t median = objects.size() >> 1;
		std::nth_element(objects.begin(), objects.begin() + median, objects.end(), ObjectComparator(node->axis));
		node->position = objects[median]->world_bounds().center()[node->axis];

		node->left = new Node();
		node->right = new Node();

		std::vector<std::shared_ptr<Traceable>> leftList(median);
		std::vector<std::shared_ptr<Traceable>> rightList(objects.size() - median);
		std::copy(objects.begin(), objects.begin() + median, leftList.begin());
		std::copy(objects.begin() + median, objects.end(), rightList.begin());

		build_recursive(node->left, depth + 1, leftList);
		build_recursive(node->right, depth + 1, rightList);
	}
void PhotonAccelerator::build_recursive(int left_index, int right_index, BVHNode *node, int depth) {
	static int MAX_NUM_PRIMITIVES_IN_LEAF = 4;
	static int MAX_DEPTH = 20;

	int n_objs = right_index - left_index;
	if (n_objs <= MAX_NUM_PRIMITIVES_IN_LEAF || depth == MAX_DEPTH) {
		node->makeLeaf(left_index, n_objs);
	} else {
		// Sort the hitpoints along the largest axis
		AABB& node_box = node->getAABB();
		int sort_dim = node_box.getLargestAxis();
		std::sort(hps.begin() + left_index, hps.begin() + right_index, [&] (Hitpoint* a, Hitpoint* b) -> bool {
			float ca = a->is.mPosition(sort_dim);
			float cb = b->is.mPosition(sort_dim);
			return ca < cb;
		});

		// Find split index
		float mid = (node_box.mMax(sort_dim) + node_box.mMin(sort_dim)) * 0.5f;
		int split_index = left_index;
		float cb;
		do {
			cb = hps[split_index++]->is.mPosition(sort_dim);
		} while (cb <= mid && split_index < right_index);
		if (split_index == left_index || split_index == right_index) {
			split_index = static_cast<int>((left_index + right_index - 1) * 0.5f + 0.5f);
		}

		// Create left and right nodes with AABB
		BVHNode left_node;
		BVHNode right_node;
		AABB& left_box = left_node.getAABB();
		AABB& right_box = right_node.getAABB();
		std::for_each(hps.begin() + left_index, hps.begin() + split_index, [&] (Hitpoint* hp) {
			AABB aabb(hp->is.mPosition);
			aabb.grow(hp->radius);
			left_box.include(aabb);
		});
		std::for_each(hps.begin() + split_index, hps.begin() + right_index, [&] (Hitpoint* hp) {
			AABB aabb(hp->is.mPosition);
			aabb.grow(hp->radius);
			right_box.include(aabb);
		});
		int n_nodes = nodes.size();
		nodes.push_back(left_node);
		nodes.push_back(right_node);

		// Initiate current node as interior node
		node->makeNode(n_nodes);

		// Recurse
		build_recursive(left_index, split_index, &nodes[n_nodes], depth + 1);
		build_recursive(split_index, right_index, &nodes[n_nodes + 1], depth + 1);
	}
}
void PhotonAccelerator::build(const std::vector<Hitpoint*>& hitpoints)
{
	hps = hitpoints;
	nodes.reserve(2 * hitpoints.size() - 1);
	BVHNode root;
	AABB& world_box = root.getAABB();
	std::for_each(hps.begin(), hps.end(), [&] (Hitpoint* hp) {
		AABB aabb(hp->is.mPosition);
		aabb.grow(hp->radius);
		world_box.include(aabb);
	});
	nodes.push_back(root);
	build_recursive(0, hps.size(), &nodes[0], 0);
}
Exemple #4
0
	void build()
	{
		root = new Node();
		build_recursive(root, 0, objects);
		initialized = true;
	}