Esempio n. 1
0
bool GridAccel::IntersectP(const Ray &ray) const {
	if (!gridForRefined) { // NOBOOK
		rayTests.Add(0, 1); // NOBOOK
		rayHits.Add(0, 1); // NOBOOK
	} // NOBOOK
	int rayId = ++curMailboxId;
	// Check ray against overall grid bounds
	float rayT;
	if (bounds.Inside(ray(ray.mint)))
		rayT = ray.mint;
	else if (!bounds.IntersectP(ray, &rayT))
		return false;
	Point gridIntersect = ray(rayT);
	// Set up 3D DDA for ray
	float NextCrossingT[3], DeltaT[3];
	int Step[3], Out[3], Pos[3];
	for (int axis = 0; axis < 3; ++axis) {
		// Compute current voxel for axis
		Pos[axis] = PosToVoxel(gridIntersect, axis);
		if (ray.d[axis] >= 0) {
			// Handle ray with positive direction for voxel stepping
			NextCrossingT[axis] = rayT +
				(VoxelToPos(Pos[axis]+1, axis) - gridIntersect[axis]) /
					ray.d[axis];
			DeltaT[axis] = Width[axis] / ray.d[axis];
			Step[axis] = 1;
			Out[axis] = NVoxels[axis];
		}
		else {
			// Handle ray with negative direction for voxel stepping
			NextCrossingT[axis] = rayT +
				(VoxelToPos(Pos[axis], axis) - gridIntersect[axis]) /
					ray.d[axis];
			DeltaT[axis] = -Width[axis] / ray.d[axis];
			Step[axis] = -1;
			Out[axis] = -1;
		}
	}
	// Walk grid for shadow ray
	for (;;) {
		int offset = Offset(Pos[0], Pos[1], Pos[2]);
		Voxel *voxel = voxels[offset];
		if (voxel && voxel->IntersectP(ray, rayId))
			return true;
		// Advance to next voxel
		// Find _stepAxis_ for stepping to next voxel
		int bits = ((NextCrossingT[0] < NextCrossingT[1]) << 2) +
			((NextCrossingT[0] < NextCrossingT[2]) << 1) +
			((NextCrossingT[1] < NextCrossingT[2]));
		const int cmpToAxis[8] = { 2, 1, 2, 1, 2, 2, 0, 0 };
		int stepAxis = cmpToAxis[bits];
		if (ray.maxt < NextCrossingT[stepAxis])
			break;
		Pos[stepAxis] += Step[stepAxis];
		if (Pos[stepAxis] == Out[stepAxis])
			break;
		NextCrossingT[stepAxis] += DeltaT[stepAxis];
	}
	return false;
}
Spectrum ExPhotonIntegrator::LPhoton(
		KdTree<Photon, PhotonProcess> *map,
		int nPaths, int nLookup, BSDF *bsdf,
		const Intersection &isect, const Vector &wo,
		float maxDistSquared) {
	Spectrum L(0.);
	if (!map) return L;
	BxDFType nonSpecular = BxDFType(BSDF_REFLECTION |
		BSDF_TRANSMISSION | BSDF_DIFFUSE | BSDF_GLOSSY);
	if (bsdf->NumComponents(nonSpecular) == 0)
		return L;
	static StatsCounter lookups("Photon Map", "Total lookups"); // NOBOOK
	// Initialize _PhotonProcess_ object, _proc_, for photon map lookups
	PhotonProcess proc(nLookup, isect.dg.p);
	proc.photons =
		(ClosePhoton *)alloca(nLookup * sizeof(ClosePhoton));
	// Do photon map lookup
	++lookups;  // NOBOOK
	map->Lookup(isect.dg.p, proc, maxDistSquared);
	// Accumulate light from nearby photons
	static StatsRatio foundRate("Photon Map", "Photons found per lookup"); // NOBOOK
	foundRate.Add(proc.foundPhotons, 1); // NOBOOK
	// Estimate reflected light from photons
	ClosePhoton *photons = proc.photons;
	int nFound = proc.foundPhotons;
	Normal Nf = Dot(wo, bsdf->dgShading.nn) < 0 ? -bsdf->dgShading.nn :
		bsdf->dgShading.nn;

	if (bsdf->NumComponents(BxDFType(BSDF_REFLECTION |
			BSDF_TRANSMISSION | BSDF_GLOSSY)) > 0) {
		// Compute exitant radiance from photons for glossy surface
		for (int i = 0; i < nFound; ++i) {
			const Photon *p = photons[i].photon;
			BxDFType flag = Dot(Nf, p->wi) > 0.f ?
				BSDF_ALL_REFLECTION : BSDF_ALL_TRANSMISSION;
			float k = kernel(p, isect.dg.p, maxDistSquared);
			L += (k / nPaths) * bsdf->f(wo, p->wi, flag) * p->alpha;
		}
	}
	else {
		// Compute exitant radiance from photons for diffuse surface
		Spectrum Lr(0.), Lt(0.);
		for (int i = 0; i < nFound; ++i) {
			if (Dot(Nf, photons[i].photon->wi) > 0.f) {
				float k = kernel(photons[i].photon, isect.dg.p,
					maxDistSquared);
				Lr += (k / nPaths) * photons[i].photon->alpha;
			}
			else {
				float k = kernel(photons[i].photon, isect.dg.p,
					maxDistSquared);
				Lt += (k / nPaths) * photons[i].photon->alpha;
			}
		}
		L += Lr * bsdf->rho(wo, BSDF_ALL_REFLECTION) * INV_PI +
			Lt * bsdf->rho(wo, BSDF_ALL_TRANSMISSION) * INV_PI;
	}
	return L;
}
Esempio n. 3
0
bool Voxel::Intersect(const Ray &ray,
                      Intersection *isect,
					  int rayId) {
	// Refine primitives in voxel if needed
	if (!allCanIntersect) {
		MailboxPrim **mpp;
		if (nPrimitives == 1) mpp = &onePrimitive;
		else mpp = primitives;
		for (u_int i = 0; i < nPrimitives; ++i) {
			MailboxPrim *mp = mpp[i];
			// Refine primitive in _mp_ if it's not intersectable
			if (!mp->primitive->CanIntersect()) {
				vector<Reference<Primitive> > p;
				mp->primitive->FullyRefine(p);
				Assert(p.size() > 0); // NOBOOK
				if (p.size() == 1)
					mp->primitive = p[0];
				else
					mp->primitive = new GridAccel(p, true, false);
			}
		}
		allCanIntersect = true;
	}
	// Loop over primitives in voxel and find intersections
	bool hitSomething = false;
	MailboxPrim **mpp;
	if (nPrimitives == 1) mpp = &onePrimitive;
	else mpp = primitives;
	for (u_int i = 0; i < nPrimitives; ++i) {
		MailboxPrim *mp = mpp[i];
		// Do mailbox check between ray and primitive
		if (mp->lastMailboxId == rayId)
			continue;
		// Check for ray--primitive intersection
		mp->lastMailboxId = rayId;
		rayTests.Add(1, 0); // NOBOOK
		if (mp->primitive->Intersect(ray, isect)) {
			rayHits.Add(1, 0); // NOBOOK
			hitSomething = true;
		}
	}
	return hitSomething;
}
Esempio n. 4
0
bool
IrradianceCache::InterpolateIrradiance(const Scene *scene,
		const Point &p, const Normal &n, Spectrum *E) const {
	if (!octree) return false;
	IrradProcess proc(n, maxError);
	octree->Lookup(p, proc);
	// Update irradiance cache lookup statistics
	static StatsPercentage nSuccessfulLookups("Irradiance Cache",
		"Successful irradiance cache lookups");
	static StatsRatio nSamplesFound("Irradiance Cache",
		"Irradiance samples found per successful lookup");
	static StatsRatio nSamplesChecked("Irradiance Cache",
		"Irradiance samples checked per lookup");
	nSuccessfulLookups.Add(proc.Successful() ? 1 : 0, 1);
	nSamplesFound.Add(proc.nFound, 1);
	nSamplesChecked.Add(proc.samplesChecked, 1);
	if (!proc.Successful()) return false;
	*E = proc.GetIrradiance();
	return true;
}
Esempio n. 5
0
// GridAccel Method Definitions
GridAccel::GridAccel(const vector<Reference<Primitive> > &p,
		bool forRefined, bool refineImmediately)
	: gridForRefined(forRefined) {
	// Initialize _prims_ with primitives for grid
	vector<Reference<Primitive> > prims;
	if (refineImmediately)
		for (u_int i = 0; i < p.size(); ++i)
			p[i]->FullyRefine(prims);
	else
		prims = p;
	// Initialize mailboxes for grid
	nMailboxes = prims.size();
	mailboxes = (MailboxPrim *)AllocAligned(nMailboxes *
		sizeof(MailboxPrim));
	for (u_int i = 0; i < nMailboxes; ++i)
		new (&mailboxes[i]) MailboxPrim(prims[i]);
	// Compute bounds and choose grid resolution
	for (u_int i = 0; i < prims.size(); ++i)
		bounds = Union(bounds, prims[i]->WorldBound());
	Vector delta = bounds.pMax - bounds.pMin;
	// Find _voxelsPerUnitDist_ for grid
	int maxAxis = bounds.MaximumExtent();
	float invMaxWidth = 1.f / delta[maxAxis];
	Assert(invMaxWidth > 0.f); // NOBOOK
	float cubeRoot = 3.f * powf(float(prims.size()), 1.f/3.f);
	float voxelsPerUnitDist = cubeRoot * invMaxWidth;
	for (int axis = 0; axis < 3; ++axis) {
		NVoxels[axis] =
		     Round2Int(delta[axis] * voxelsPerUnitDist);
		NVoxels[axis] = Clamp(NVoxels[axis], 1, 64);
	}
	// Compute voxel widths and allocate voxels
	for (int axis = 0; axis < 3; ++axis) {
		Width[axis] = delta[axis] / NVoxels[axis];
		InvWidth[axis] =
		    (Width[axis] == 0.f) ? 0.f : 1.f / Width[axis];
	}
	int nVoxels = NVoxels[0] * NVoxels[1] * NVoxels[2];
	voxels = (Voxel **)AllocAligned(nVoxels * sizeof(Voxel *));
	memset(voxels, 0, nVoxels * sizeof(Voxel *));
	// Add primitives to grid voxels
	for (u_int i = 0; i < prims.size(); ++i) {
		// Find voxel extent of primitive
		BBox pb = prims[i]->WorldBound();
		int vmin[3], vmax[3];
		for (int axis = 0; axis < 3; ++axis) {
			vmin[axis] = PosToVoxel(pb.pMin, axis);
			vmax[axis] = PosToVoxel(pb.pMax, axis);
		}
		// Add primitive to overlapping voxels
		for (int z = vmin[2]; z <= vmax[2]; ++z)
			for (int y = vmin[1]; y <= vmax[1]; ++y)
				for (int x = vmin[0]; x <= vmax[0]; ++x) {
					int offset = Offset(x, y, z);
					if (!voxels[offset]) {
						// Allocate new voxel and store primitive in it
						voxels[offset] = new (voxelArena) Voxel(&mailboxes[i]);
					}
					else {
						// Add primitive to already-allocated voxel
						voxels[offset]->AddPrimitive(&mailboxes[i]);
					}
				}
		static StatsRatio nPrimitiveVoxels("Grid Accelerator", // NOBOOK
			"Voxels covered vs # / primitives"); // NOBOOK
		nPrimitiveVoxels.Add((1 + vmax[0]-vmin[0]) * (1 + vmax[1]-vmin[1]) * // NOBOOK
			(1 + vmax[2]-vmin[2]), 1); // NOBOOK
	}
	// Update grid statistics
	static StatsPercentage nEmptyVoxels("Grid Accelerator",
	                                    "Empty voxels");
	static StatsRatio avgPrimsInVoxel("Grid Accelerator",
		"Average # of primitives in voxel");
	static StatsCounter maxPrimsInVoxel("Grid Accelerator",
		"Max # of primitives in a grid voxel");
	nEmptyVoxels.Add(0, NVoxels[0] * NVoxels[1] * NVoxels[2]);
	avgPrimsInVoxel.Add(0,NVoxels[0] * NVoxels[1] * NVoxels[2]);
	for (int z = 0; z < NVoxels[2]; ++z)
		for (int y = 0; y < NVoxels[1]; ++y)
			for (int x = 0; x < NVoxels[0]; ++x) {
				int offset = Offset(x, y, z);
				if (!voxels[offset]) nEmptyVoxels.Add(1, 0);
				else {
				    int nPrims = voxels[offset]->nPrimitives;
					maxPrimsInVoxel.Max(nPrims);
					avgPrimsInVoxel.Add(nPrims, 0);
				}
			}
}