void Photonmap::BalanceSegment( Photon* porg , int index , int st , int en ) {
	if ( st == en ) {
		photons[index] = porg[st];
		return;
	}

	int med = 1;
	while ( 4 * med <= en - st + 1 ) med <<= 1;

	if ( 3 * med <= en - st + 1 ) med = med * 2 + st - 1;
		else med = en + 1 - med;
	
	int axis = 2;
	if ( box_max.x - box_min.x > box_max.y - box_min.y && box_max.x - box_min.x > box_max.z - box_min.z ) axis = 0; else
	if ( box_max.y - box_min.y > box_max.z - box_min.z ) axis = 1;

	MedianSplit( porg , st , en , med , axis );
	photons[index] = porg[med];
	photons[index].plane = axis;

	if ( st < med ) {
		double tmp = box_max.GetCoord( axis );
		box_max.GetCoord( axis ) = photons[index].pos.GetCoord( axis );
		BalanceSegment( porg , index * 2 , st , med - 1 );
		box_max.GetCoord( axis ) = tmp;
	}

	if ( med < en ) {
		double tmp = box_min.GetCoord( axis );
		box_min.GetCoord( axis ) = photons[index].pos.GetCoord( axis );
		BalanceSegment( porg , index * 2 + 1 , med + 1 , en );
		box_min.GetCoord( axis ) = tmp;
	}
}
void Photonmap::Balance() {
	Photon* porg = new Photon[stored_photons + 1];

	for ( int i = 0 ; i <= stored_photons ; i++ )
		porg[i] = photons[i];
	
	BalanceSegment( porg , 1 , 1 , stored_photons );
	delete[] porg;
}
Beispiel #3
0
	void Balance(bool complete) {
		if (!complete) {
			// photon-map was not filled to capacity;
			// this means we must now get rid of the
			// excess reserved NULL nodes
			size_t nullNodeIdx = 1;

			// find the first node that is still NULL
			while (nullNodeIdx < nodes.size() && nodes[nullNodeIdx] != NULL) {
				nullNodeIdx++;
			}

			// shrink the vector
			if (nullNodeIdx < nodes.size()) {
				nodes.resize(nullNodeIdx);
			}
		}

		if (nodes.size() > 1) {
			// use two temporary buffers for balancing
			//
			// at every level of the recursion, these
			// represent and store the left and right
			// subtrees with respect to the new median
			// point along the splitting axis (subtrees
			// are delineated by start- and end-indices)
			//
			// note: could we do this in-place instead?
			std::vector<T> lftSegment(nodes.size(), NULL);
			std::vector<T> rgtSegment(nodes.size(), NULL);

			for (size_t i = 0; i < nodes.size(); i++) {
				lftSegment[i] = NULL;
				rgtSegment[i] = nodes[i];
			}

			BalanceSegment(lftSegment, rgtSegment, 1, 1, (nodes.size() - 1));
			BuildHeap(lftSegment);
		}
	}
Beispiel #4
0
	void BalanceSegment(
		std::vector<T>& lftSegment,
		std::vector<T>& rgtSegment,
		const int rNodeNum, // index of node representing root of segment
		const int sNodeNum, // index of node representing start of segment
		const int eNodeNum  // index of node representing end of segment
	) {
		assert(sNodeNum >=                     0);
		assert(eNodeNum < int(lftSegment.size()));

		int newMedianIdx = 1;
		int splitAxisIdx = 2;

		{
			// compute index of new median node based on start- and end-node indices (?)
			while ((4 * newMedianIdx) <= (eNodeNum - sNodeNum + 1)) {
				newMedianIdx <<= 1;
			}

			if ((3 * newMedianIdx) <= (eNodeNum - sNodeNum + 1)) {
				newMedianIdx <<= 1;
				newMedianIdx += (sNodeNum - 1);
			} else {
				newMedianIdx = eNodeNum - newMedianIdx + 1;
			}
		}

		{
			// find the axis to split along
			if (((maxs.x - mins.x) > (maxs.y - mins.y)) && ((maxs.x - mins.x) > (maxs.z - mins.z))) {
				splitAxisIdx = 0;
			} else {
				if ((maxs.y - mins.y) > (maxs.z - mins.z)) {
					splitAxisIdx = 1;
				}
			}
		}

		// partition block of nodes around the new median
		MedianSplitSegment(rgtSegment, sNodeNum, eNodeNum, newMedianIdx, splitAxisIdx);

		lftSegment[rNodeNum] = rgtSegment[newMedianIdx];
		lftSegment[rNodeNum]->SetAxis(splitAxisIdx);

		{
			if (newMedianIdx > sNodeNum) {
				// recursively balance the left block
				if (sNodeNum < (newMedianIdx - 1)) {
					const float v = maxs[splitAxisIdx];

					maxs[splitAxisIdx] = lftSegment[rNodeNum]->GetPos()[splitAxisIdx];
					BalanceSegment(lftSegment, rgtSegment, (rNodeNum << 1), sNodeNum, newMedianIdx - 1);
					maxs[splitAxisIdx] = v;
				} else {
					lftSegment[(rNodeNum << 1)] = rgtSegment[sNodeNum];
				}
			}

			if (newMedianIdx < eNodeNum) {
				// recursively balance the right block
				if ((newMedianIdx + 1) < eNodeNum) {
					const float v = mins[splitAxisIdx];

					mins[splitAxisIdx] = lftSegment[rNodeNum]->GetPos()[splitAxisIdx];
					BalanceSegment(lftSegment, rgtSegment, (rNodeNum << 1) + 1, newMedianIdx + 1, eNodeNum);
					mins[splitAxisIdx] = v;
				} else {
					lftSegment[(rNodeNum << 1) + 1] = rgtSegment[eNodeNum];
				}
			}
		}
	}