EmitterSampler.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   EmitterSampler.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Sampler which selects a point on an emitter (light source) in the scene 
00009    with probability proportional to radiant exitance.
00010    <!-------------------------------------------------------------------->**/
00011 
00012 #include "EmitterSampler.h"
00013 #include <SurfacePoint.h>
00014 #include <ShapeSet.h>
00015 #include <Material.h>
00016 #include <Scene.h>
00017 
00018 void EmitterSampler::init(ShapeSet *lights) {
00019    ASSERT(lights);
00020    
00021    m_lights = lights;
00022    m_n      = m_lights->size();
00023    
00024    if (m_n <= 0)
00025       return;
00026    
00027    safeDeleteArray(m_cdf);
00028    m_cdf = new real_t[m_n];
00029    
00030    real_t totalPower = 0;
00031    m_area = 0;
00032    
00033    // aggregate emittance CDF
00034    for(unsigned i = m_n; i--;) {
00035       Shape *light = (*m_lights)[i];
00036       const real_t power = 
00037          light->getMaterial()->getEmitter()->getPower().getAverage();
00038       
00039       m_cdf[i]    = power;
00040       totalPower += power;
00041       m_area     += light->getSurfaceArea();
00042    }
00043    
00044    // normalize CDF
00045    ASSERT(totalPower > 0);
00046    for(unsigned i = m_n; i--;)
00047       m_cdf[i] /= totalPower;
00048 }
00049 
00050 Event EmitterSampler::sample() {
00051    ASSERT(m_n > 0);
00052    
00053    // sample a light source index from the normalized CDF
00054    const unsigned emitterIndex = Random::sampleNormalizedCDF(m_cdf, m_n);
00055    ASSERT(emitterIndex < m_n);
00056    SurfacePoint *pt = new SurfacePoint();
00057    
00058    (*m_lights)[emitterIndex]->getRandomPoint(*pt);
00059    return Event(pt, this, emitterIndex);
00060 }
00061 
00062 real_t EmitterSampler::getPdf(const Event &event) {
00063    ASSERT(m_n > 0);
00064    unsigned emitterIndex = m_n;
00065    
00066    if (event.hasMetadata()) {
00067       emitterIndex = event.getMetadata<unsigned>();
00068    } else {
00069       const SurfacePoint *pt = event.getValue<SurfacePoint*>();
00070       
00071       // determine which light source the given event lies on
00072       for(unsigned i = m_n; i--;) {
00073          if (pt->shape == (*m_lights)[i]) {
00074             emitterIndex = i;
00075             break;
00076          }
00077       }
00078    }
00079    
00080    ASSERT(emitterIndex < m_n);
00081    if (emitterIndex >= m_n)
00082       emitterIndex = m_n - 1;
00083    
00084    // sampling with respect to emitted power, but 
00085    Shape *shape  = (*m_lights)[emitterIndex];
00086    real_t area   = shape->getSurfaceArea();
00087    if (area <= EPSILON)
00088       area = 1;
00089    
00090    // TODO: verify correctness
00091    //real_t pPower = m_cdf[emitterIndex];
00092    real_t pArea  = (m_area > 0 ? 1.0 / m_area : 1);
00093    //real_t pConv  = pPower / pArea; // / area
00094    
00095    return pArea;//pConv;
00096 }
00097 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6