public virtual void irradianceEstimate(RGBColor irrad, Vector3D position, Vector3D normal, float maxDist, int noPhotons) { float ALPHA = 0.918f; float MBETA = -1.953f; float DENOMFACTOR = 1.0f / (1.0f - (float)System.Math.Exp(MBETA)); NearestPhotons np = new NearestPhotons(noPhotons, maxDist, position); irrad.set(0.0f); // locate the nearest photons locatePhotons(np, 1); // if less than MINPHOTONS return if (np.found < photontracer.SceneConstants.MIN_PHOTONS) { return; } Vector3D direction = new Vector3D(); float mittrs = MBETA / (2.0f * (float)np.dist2[0]); // sum irrandiance from all photons for (int i = 1; i <= np.found; i++) { Photon p = getPhoton(np.indices[i]); // the toCartesian call and following if can be omitted (for speed) // if the scene does not have any thin surfaces p.toCartesian(direction); if (direction.dot(normal) < 0.0) { float gaussWeight = 1.0f - (1.0f - (float)System.Math.Exp((float)p.position.distanceSqr(position) * mittrs)) * DENOMFACTOR; irrad.add(p.power.scaleNew(gaussWeight)); } } // estimate of density irrad.scale(ALPHA / (float)(System.Math.PI * np.dist2[0])); }
public virtual Photon store(RGBColor power, Vector3D position, Vector3D direction, Vector3D surfaceNormal) { storedPhotons_++; Photon photon = new Photon(); photon.precomputedIrradiance = false; photon.power = new RGBColor(power); photon.position = new Vector3D(position); photon.number = storedPhotons_; photon.toSpherical(direction); photon.surfaceToSpherical(surfaceNormal); position.updateMinMax(bboxMin, bboxMax); photons.Add(photon); return(photon); }
public void ThreadProc() { Vector3D surfaceDirection = new Vector3D(); for (int i = start; i <= stop; i++) { Photon p = mainInstance.getPhoton(i); p.accumPower = new RGBColor(); p.surfaceToCartesian(surfaceDirection); mainInstance.radianceEstimate(p.accumPower, p.position, surfaceDirection, maxDist, noPhotons); p.precomputedIrradiance = true; } // signal! lock (this) { done = true; } }
public virtual void balance() { if (storedPhotons_ > 1) { Photon[] pa1; Photon[] pa2; pa1 = new Photon[storedPhotons_ + 1]; pa2 = new Photon[storedPhotons_ + 1]; for (int i = 0; i <= storedPhotons_; i++) { pa2[i] = getPhoton(i); } balanceSegment(pa1, pa2, 1, 1, storedPhotons_); // reorganise balance kd-tree (make a heap) int foo = 1; int j = 1; int d; Photon fooPhoton = getPhoton(j); for (int i = 1; i <= storedPhotons_; i++) { d = pa1[j].number; pa1[j] = null; if (d != foo) { photons[j] = getPhoton(d); getPhoton(d); } else { photons[j] = fooPhoton; System.Object generatedAux = fooPhoton; if (i < storedPhotons_) { for (; foo <= storedPhotons_; foo++) { if (pa1[foo] != null) { break; } } fooPhoton = getPhoton(foo); j = foo; } continue; } j = d; } } halfStoredPhotons = (storedPhotons_ / 2) - 1; }
public virtual void locatePhotonsPrecomputed(Vector3D normal, NearestPhotons np, int index) { double dist1, dist2; Photon p = getPhoton(index); if (index < halfStoredPhotons) { dist1 = np.position.get(p.plane) - p.position.get(p.plane); if (dist1 > 0.0) { // if dist1 is positive search right plane locatePhotonsPrecomputed(normal, np, (2 * index) + 1); if (dist1 * dist1 < np.dist2[0]) { locatePhotonsPrecomputed(normal, np, (2 * index)); } } else { // dist1 is negative search left first locatePhotonsPrecomputed(normal, np, (2 * index)); if (dist1 * dist1 < np.dist2[0]) { locatePhotonsPrecomputed(normal, np, (2 * index) + 1); } } } // compute squared distance between current photon and np.position dist2 = p.position.distanceSqr(np.position); //assert(p.precomputedIrradiance); //assert(np.max == 1); Vector3D surfaceDirection = new Vector3D(); p.surfaceToCartesian(surfaceDirection); //System.out.println(normal.dot(surfaceDirection)); if (dist2 < np.dist2[0] && normal.dot(surfaceDirection) > 0.0) { // we found a photon :) Insert it in the candidate list if (np.found < 1) { // heap is not full; use array np.found++; np.dist2[np.found] = dist2; np.indices[np.found] = index; } else { // exchange element if necessary if (np.dist2[0] > dist2) { np.dist2[1] = dist2; np.indices[1] = index; np.dist2[0] = dist2; } } } }
public virtual void locatePhotons(NearestPhotons np, int index) { double dist1, dist2; Photon p = getPhoton(index); if (index < halfStoredPhotons) { dist1 = np.position.get(p.plane) - p.position.get(p.plane); if (dist1 > 0.0) { // if dist1 is positive search right plane locatePhotons(np, (2 * index) + 1); if (dist1 * dist1 < np.dist2[0]) { locatePhotons(np, (2 * index)); } } else { // dist1 is negative search left first locatePhotons(np, (2 * index)); if (dist1 * dist1 < np.dist2[0]) { locatePhotons(np, (2 * index) + 1); } } } // compute squared distance between current photon and np.position dist2 = p.position.distanceSqr(np.position); 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.indices[np.found] = index; } else { int j, parent; if (!np.gotHeap) { // build heap int halfFound; int photIndex; double tempDist; halfFound = np.found >> 1; for (int k = halfFound; k >= 1; k--) { parent = k; photIndex = np.indices[k]; tempDist = np.dist2[k]; while (parent < halfFound) { j = parent + parent; if (j < np.found && np.dist2[j] < np.dist2[j + 1]) { j++; } if (tempDist >= np.dist2[j]) { break; } np.dist2[parent] = np.dist2[j]; np.indices[parent] = np.indices[j]; parent = j; } np.dist2[parent] = tempDist; np.indices[parent] = photIndex; } np.gotHeap = true; } // 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.indices[parent] = np.indices[j]; parent = j; j += j; } //!!! if (dist2 < np.dist2[parent]) { np.dist2[parent] = dist2; np.indices[parent] = index; } np.dist2[0] = np.dist2[1]; } } }