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
1.5.6