I'm working on my first ray tracer and I've run into a pretty confusing problem while trying to implement progressive photon mapping. I seem to have created a tangled web of pointer madness, and I'll try to explain the reason behind it.
I have an object, Integrator, that contains a vector of P_HitPoint objects, a vector of P_HitPoint* (which contains one pointer for each object in the P_HitPoint vector) and a KD Tree object. The constructor for the KD tree looks like this:
1 2 3 4 5
|
KDT::KDT(const std::vector<P_HitPoint*> &_hitpoints)
{
std::vector<P_HitPoint*> hitpoints(_hitpoints);
root = *buildKDTree(hitpoints, 0);
}
| |
What this
should do is create a KD Tree where each node contains a pointer to a P_HitPoint object in the Integrator, and this part seems to work. The KD Tree builds just fine, and I can access the HitPoint that each node points to.
The reason I'm using a vector of pointers instead of the vector of P_HitPoints itself is because I want to be able to alter data inside the P_HitPoint objects outside of the KD Tree (the only thing that will stay constant is their position, and that's all the KD Tree needs). Each time a photon lands inside the radius of a P_HitPoint the flux and radius of that P_HitPoint have to be updated, and this is done in the Integrator. BUT the KD Tree has to be able to use this updated radius when doing nearest neighbor searches, at least that's the idea.
Now here's the problem. I want to get a list of pointers to the nearest neighbors of a given photon from the KD Tree, these should be pointers to P_HitPoints in the original P_HitPoint vector. I call the nearestneighbor search in KDT like so:
std::vector<P_HitPoint*> nearest = hptree.gatherNearest(_pho.p);
The method inside KDT is here:
1 2 3 4 5 6 7 8 9 10
|
std::vector<P_HitPoint*> KDT::gatherNearest(const Point &_p)
{
std::vector<P_HitPoint*> ret;
//The root node is always sorted along x, so we start the comparison on x axis
if (_p.x < root.hp->position.x)
findClosestHitPoints(_p, root.leftChild, 1, ret);
else
findClosestHitPoints(_p, root.rightChild, 1, ret);
return ret;
| |
And finally the method that does the recursive search (which isn't quite right to begin with, but that's another story):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
void KDT::findClosestHitPoints(const Point &_p, Node* _me, int depth, std::vector<P_HitPoint*> _result)
{
if (_me == NULL)
return;
if (_me->leftChild == NULL || _me->rightChild == NULL)
return;
int axis = depth % 3;
bool inside = false;
if (isInsideRegion(_p, _me->hp->r2, _me->hp))
{
_result.push_back(&(*(_me->hp)));
inside = true;
}
depth++;
//Since this point was inside the radius, we want to search both child nodes
if (inside)
{
findClosestHitPoints(_p, _me->rightChild, depth, _result);
findClosestHitPoints(_p, _me->leftChild, depth, _result);
} else {
//Compare values based on which axis we're in
switch(axis) {
case 0:
if (_p.x < _me->hp->position.x)
findClosestHitPoints(_p, _me->leftChild, depth, _result);
else
findClosestHitPoints(_p, _me->rightChild, depth, _result);
break;
case 1:
if (_p.y < _me->hp->position.y)
findClosestHitPoints(_p, _me->leftChild, depth, _result);
else
findClosestHitPoints(_p, _me->rightChild, depth, _result);
break;
case 2:
if (_p.z < _me->hp->position.z)
findClosestHitPoints(_p, _me->leftChild, depth, _result);
else
findClosestHitPoints(_p, _me->rightChild, depth, _result);
break;
default:
return;
}
}
}
| |
So the basic idea is to create a vector of P_HitPoint*, pass this to the recursive search and have it add the pointer stored in a node to this vector if it satisfies the criteria. Then at the end I return this vector of pointers back to the integrator.
Problem is, as the recursive search runs it DOES add pointers to the result vector, but then as it backs up to the root node those pointers disappear again, and at the end I'm left with an empty vector that gets returned to the getNearest() method and passed back to the Integrator. I take it they're going out of scope as the recursion ends, so is there any way to make this work? Or maybe a less convoluted way of doing this, without a vector of pointers?
Sorry for the length