//OK //irradiance_estimate computes an irradiance estimate // at a given surface position public RGBColor IrradianceEstimate(Point3D pos, Vector3D normal, float max_dist, int nphotons) { RGBColor irrad = RGBColor.Black; NearestPhotons np = new NearestPhotons(); np.Dist2 = new float[nphotons + 1]; np.Index = new Photon[nphotons + 1]; np.Pos = pos; np.Max = nphotons; np.Found = 0; np.GotHeap = 0; np.Dist2[0] = max_dist * max_dist; // locate the nearest photons this.LocatePhotons(np, 1); // if less than 8 photons return if (np.Found < 8) { return(irrad); } Vector3D pdir; // sum irradiance from all photons for (int i = 1; i <= np.Found; i++) { Photon p = np.Index[i]; // the photon_dir call and following if can be omitted (for speed) // if the scene does not have any thin surfaces pdir = this.photonDir(p); if ((pdir * normal) < 0.0f) { irrad += p.Power; } } float tmp = (float)((1.0f / Math.PI) / (np.Dist2[0])); // estimate of // density irrad *= tmp; //Use Array.Clear(); np.Dist2 = null; np.Index = null; return(irrad); }
//OK // locate_photons finds the nearest photons in the // photon map given the parameters in np private void LocatePhotons(NearestPhotons np, int index) { Photon p = this.Photons[index]; if (index < this.half_stored_photons) { float dist1 = np.Pos[p.Plane] - p.Position[p.Plane]; if (dist1 > 0.0) { // if dist1 is positive search right plane this.LocatePhotons(np, 2 * index + 1); if (dist1 * dist1 < np.Dist2[0]) { this.LocatePhotons(np, 2 * index); } } else { // dist1 is negative search left first this.LocatePhotons(np, 2 * index); if (dist1 * dist1 < np.Dist2[0]) { this.LocatePhotons(np, 2 * index + 1); } } } // compute squared distance between current photon and np.pos //dist1 = p.pos[0] - np.pos[0]; //float dist2 = dist1 * dist1; //dist1 = p.pos[1] - np.pos[1]; //dist2 += dist1 * dist1; //dist1 = p.pos[2] - np.pos[2]; //dist2 += dist1 * dist1; float dist2 = (p.Position - np.Pos).Length2; if (dist2 < np.Dist2[0]) { // we found a photon :) Insert it in the candidate list if (np.Found < np.Max) { // heap is not full; use array np.Found++; np.Dist2[np.Found] = dist2; np.Index[np.Found] = p; } else { int j, parent; if (np.GotHeap == 0) { // Do we need to build the heap? // Build heap float dst2; Photon phot; int half_found = np.Found >> 1; for (int k = half_found; k >= 1; k--) { parent = k; phot = np.Index[k]; dst2 = np.Dist2[k]; while (parent <= half_found) { j = parent + parent; if (j < np.Found && np.Dist2[j] < np.Dist2[j + 1]) { j++; } if (dst2 >= np.Dist2[j]) { break; } np.Dist2[parent] = np.Dist2[j]; np.Index[parent] = np.Index[j]; parent = j; } np.Dist2[parent] = dst2; np.Index[parent] = phot; } np.GotHeap = 1; } // insert new photon into max heap // delete largest element, insert new and reorder the heap parent = 1; j = 2; while (j <= np.Found) { if (j < np.Found && np.Dist2[j] < np.Dist2[j + 1]) { j++; } if (dist2 > np.Dist2[j]) { break; } np.Dist2[parent] = np.Dist2[j]; np.Index[parent] = np.Index[j]; parent = j; j += j; } if (dist2 < np.Dist2[parent]) { np.Index[parent] = p; np.Dist2[parent] = dist2; } np.Dist2[0] = np.Dist2[1]; } } }
//OK //irradiance_estimate computes an irradiance estimate // at a given surface position public RGBColor IrradianceEstimate(Point3D pos, Vector3D normal, float max_dist, int nphotons) { RGBColor irrad = RGBColor.Black; NearestPhotons np = new NearestPhotons(); np.Dist2 = new float[nphotons + 1]; np.Index = new Photon[nphotons + 1]; np.Pos = pos; np.Max = nphotons; np.Found = 0; np.GotHeap = 0; np.Dist2[0] = max_dist * max_dist; // locate the nearest photons this.LocatePhotons(np, 1); // if less than 8 photons return if (np.Found < 8) { return irrad; } Vector3D pdir; // sum irradiance from all photons for (int i = 1; i <= np.Found; i++) { Photon p = np.Index[i]; // the photon_dir call and following if can be omitted (for speed) // if the scene does not have any thin surfaces pdir = this.photonDir(p); if ((pdir * normal) < 0.0f) { irrad += p.Power; } } float tmp = (float) ((1.0f / Math.PI) / (np.Dist2[0])); // estimate of // density irrad *= tmp; //Use Array.Clear(); np.Dist2 = null; np.Index = null; return irrad; }