src/rcrt/lights/SphericalLight.cpp

Go to the documentation of this file.
00001 #include "SphericalLight.h"
00002 
00003 namespace rcrt
00004 {
00005 
00006 SphericalLight::SphericalLight(const RGBColor& power, const float& rad, const Point3D& c, const int& samp):
00007         Light(power, samp),radius(rad),center(c), radius2(rad*rad)
00008 {
00009         
00010 }
00011 
00012 SphericalLight::~SphericalLight()
00013 {
00014 }
00015 
00016 
00017 LightSample SphericalLight::illuminate(const Point3D& p, const Vec3D& normal) const
00018 {
00019         Vec3D dir = center - p;
00020         float distSqr = dir * dir;
00021         if(distSqr <= radius2)
00022         {
00023                 return LightSample(0,0,0,0);
00024         }
00025         float dist = sqrt(distSqr);
00026         float idistSqr = 1.f/(distSqr);
00027         float cosAlpha = std::sqrt(1.f - radius2 * idistSqr);
00028         dir = dir * 1.f/dist;
00029         Vec3D du, dv;
00030         dir.getCS(du, dv);
00031         const float xi1 = float(rand()) / float(RAND_MAX);
00032         const float xi2 = float(rand()) / float(RAND_MAX);
00033         double cosAng = 1.0 - (1.0-(double)cosAlpha) * xi2;
00034         double sinAng = sqrt(1.0 - cosAng*cosAng);
00035         float t1 = 2.0*M_PI*xi1;
00036         Vec3D sampleDir((du*cos(t1) + dv*sin(t1))*sinAng + dir*cosAng); 
00037                 
00038         const Vec3D vf = p - center;
00039         const float ea = sampleDir * sampleDir;
00040         const float eb = 2.0*vf*sampleDir;
00041         const float ec = vf*vf-radius2+0.00001f;
00042         const float osc = eb*eb-4.0*ea*ec;
00043         float d1;
00044         if(osc < 0) {
00045                 d1 = sqrt(ec/ea);
00046         } else {
00047                 d1 = (-eb-sqrt(osc))/(2.0*ea);
00048         }
00049         
00050         return LightSample(2.f * (1.f - cosAlpha), sampleDir, d1, power);
00051 }
00052 
00053 void SphericalLight::illuminate(const Point3D& p, const Vec3D& normal, std::vector<LightSample>& samples,
00054                         const int& noSamples, Scene* s) const
00055 {
00056         Vec3D dir(center-p);
00057         const float dist2 = dir * dir;
00058         if(dist2 < radius2)
00059                 return;
00060         const float cosThetaMax(sqrt(std::max(0.0f, 1.0f - radius2 / (dist2  * 0.01f + float(sqrt(dist2)) * 0.25f + 1))));
00061         const float scale(2.0f * M_PI * (1.0f - cosThetaMax));
00062         const float weight(scale / noSamples);
00063         for(int i = 0; i < noSamples; i++){
00064                 samples.push_back(illuminate(p, normal));
00065                 samples.back().setWeight(weight);
00066         }
00067 }
00068 
00069 RGBColor SphericalLight::getEmitted(const Vec3D& dir, const Point3D& pos) const
00070 {
00071         return power;
00072 }
00073 
00074 void SphericalLight::emitPhoton(Photon* photon) const
00075 {
00076         //TODO
00077 }
00078 
00079 }

Generated on Thu Jan 31 19:26:19 2008 for RenderingCompetitionRayTracer by  doxygen 1.5.3