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);
}
void PhotonAccelerator::accumulate(const Intersection& is, Color flux)
{
	BVHNode* currentNode = &nodes[0];
	AABB& box = currentNode->getAABB();
	Point3D point = is.mPosition;
	if (!box.inside(point))
		return;
	std::stack<BVHNode> intersect_stack;
	while (true) {
		if (currentNode->isLeaf()) {
			Vector3D v(point);
			for (unsigned int i = currentNode->getIndex(); i < currentNode->getIndex() + currentNode->getNObjs(); ++i) {
				Hitpoint& hp = *hps[i];
				if ((v - hp.is.mPosition).length() <= hp.radius && hp.is.mNormal * is.mNormal >= 0) {
					hp.newPhotonCount += 1;
					hp.totalFlux += flux * hp.is.mMaterial->evalBRDF(hp.is, -is.mRay.dir);
				}
			}
		} else {
			BVHNode& left_node = nodes[currentNode->getIndex()];
			BVHNode& right_node = nodes[currentNode->getIndex() + 1];
			AABB& left_box = left_node.getAABB();
			AABB& right_box = right_node.getAABB();

			bool leftHit, rightHit;
			leftHit = left_box.inside(point);
			rightHit = right_box.inside(point);
			if (leftHit && rightHit) {
				currentNode = &left_node;
				intersect_stack.push(right_node);
				continue;
			} else if (leftHit) {
				currentNode = &left_node;
				continue;
			} else if (rightHit) {
				currentNode = &right_node;
				continue;
			}
		}
		if (intersect_stack.empty())
			return;
		currentNode = &intersect_stack.top();
		intersect_stack.pop();
	}
}