예제 #1
0
//**********************************************
void Photon_map :: irradiance_estimate(
  float irrad[3],                // returned irradiance
  const float pos[3],            // surface position
  const float normal[3],         // surface normal at pos
  const float max_dist,          // max distance to look for photons
  const int nphotons ) const     // number of photons to use
//**********************************************
{
  irrad[0] = irrad[1] = irrad[2] = 0.0;

  NearestPhotons np;
  np.dist2 = (float*)alloca( sizeof(float)*(nphotons+1) );
  np.index = (const Photon**)alloca( sizeof(Photon*)*(nphotons+1) );

  np.pos[0] = pos[0]; np.pos[1] = pos[1]; np.pos[2] = pos[2];
  np.max = nphotons;
  np.found = 0;
  np.got_heap = 0;
  np.dist2[0] = max_dist*max_dist;

  // locate the nearest photons
  locate_photons( &np, 1 );

  // if less than 8 photons return
  if (np.found<8)
    return;

  float pdir[3];

  // sum irradiance from all photons
  for (int i=1; i<=np.found; i++) {
    const 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
    photon_dir( pdir, p );
    if ( (pdir[0]*normal[0]+pdir[1]*normal[1]+pdir[2]*normal[2]) < 0.0f ) {
      irrad[0] += p->power[0];
      irrad[1] += p->power[1];
      irrad[2] += p->power[2];
    }
  }

  const float tmp=(1.0f/PI)/(np.dist2[0]);	// estimate of density

  irrad[0] *= tmp;
  irrad[1] *= tmp;
  irrad[2] *= tmp;
}
예제 #2
0
//******************************************
void PhotonMap::locate_photons(NearestPhotons *const np, const int index) const
//******************************************
{
    const Photon *p = &photons[index];
    float dist1;

    if (index < half_stored_photons) {
        dist1 = np->pos[p->plane] - p->pos[p->plane];

        if (dist1 > 0.0) { // if dist1 is positive search right plane
            locate_photons(np, 2 * index + 1);
            if (dist1 * dist1 < np->dist2[0])
                locate_photons(np, 2 * index);
        } else { // dist1 is negative search left first
            locate_photons(np, 2 * index);
            if (dist1 * dist1 < np->dist2[0])
                locate_photons(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;

    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->got_heap == 0) { // Do we need to build the heap?
                // Build heap
                float dst2;
                const 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->got_heap = 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;
            }
            np->index[parent] = p;
            np->dist2[parent] = dist2;

            np->dist2[0] = np->dist2[1];
        }
    }