src/rcrt/lights/AreaLight.cpp

Go to the documentation of this file.
00001 #include "AreaLight.h"
00002 #include <limits>
00003 #include "../math/Matrix4D.h"
00004 
00005 using namespace std;
00006 
00007 namespace rcrt
00008 {
00009 
00010 AreaLight::AreaLight(const RGBColor& p, const Point3D& pos,
00011                 const Vec3D& dir1, const Vec3D& dir2, const Vec3D& no):Light(p), base(pos),
00012                 span1(dir1), span2(dir2), 
00013                 normal(
00014                                 ((dir1.crossP(dir2)).normalize() * no < 0 ?
00015                                                 dir1.crossP(dir2) * -1
00016                                                 : dir1.crossP(dir2))
00017                                                 .normalized()
00018                                 ),
00019                 area(normal.norm()), object("arealight"), material(this),
00020                 tri1(pos, pos+dir1, pos+dir1+dir2, normal,&object),
00021                 tri2(pos+dir1+dir2, pos+dir2, pos, normal,&object)
00022                 
00023 {
00024         minSamples = 4;//(int)ceil(area*32);//TODO parameterize
00025         cout << "area = " << area << " light samplecount = " << minSamples << endl;
00026         object.setWorldMatrix(Matrix4D::identity());
00027         object.setMaterial(&material);
00028         triList.push_back(&tri1);
00029         triList.push_back(&tri2);
00030         object.setPrimitives(&triList);
00031         aspect = span2.norm()/span1.norm();
00032 }
00033 
00034 AreaLight::~AreaLight()
00035 {
00036 }
00037 
00038         
00039 /* Light methods */
00040 
00041 LightSample AreaLight::illuminate(const Point3D& p, const Vec3D& no) const
00042 {
00043         const Point3D loc(getRandomPosition());
00044         return getSample(p,no,loc);
00045 }
00046 
00047 void AreaLight::illuminate(const Point3D& p, const Vec3D& no, std::vector<LightSample>& samples,
00048                         const int& noSamples, Scene* s) const
00049 {
00050         if(noSamples == 1){
00051                 samples.push_back(getSample(p,no,base+0.5*span1+0.5*span2,s));
00052         } else if (noSamples == 4) {
00053                 samples.push_back(getSample(p,no,base+0.125*span1+0.375*span2,s));
00054                 samples.push_back(getSample(p,no,base+0.625*span1+0.125*span2,s));
00055                 samples.push_back(getSample(p,no,base+0.875*span1+0.625*span2,s));
00056                 samples.push_back(getSample(p,no,base+0.375*span1+0.875*span2,s));
00057         }
00058         int sampY = (int)floor(sqrt(noSamples*aspect));
00059         int sampX = (int)ceil(noSamples/sampY);
00060         float weight = 1.0f/(sampY*sampX);
00061         float uDist = 1.0f/sampX;
00062         float vDist = 1.0f/sampY;
00063         for(float u = 0.5; u < sampX; u++){
00064                 for(float v = 0.5; v < sampY; v++){
00065                         float xi1 = (float(rand()) / float(RAND_MAX) - 0.5) * uDist/4;
00066                         float xi2 = (float(rand()) / float(RAND_MAX) - 0.5) * vDist/4;
00067                         //cout << "u*D=" << u*uDist << " v*D=" << v*vDist << endl;
00068                         LightSample ls = getSample(
00069                                         p,no,base + (u*uDist+xi1)*span1 + (v*vDist+xi2)*span2,s);
00070                         //cout << "sample=" << ls.power() << endl;
00071                         if(ls.weight() != 0)
00072                                 ls.setWeight(weight);
00073                         samples.push_back(ls);
00074                 }
00075         }
00076 }
00077 
00078 
00079 Point3D AreaLight::getRandomPosition() const
00080 {
00081         // compute random position of a point light on the quad
00082         float xi1 = float(rand()) / float(RAND_MAX);
00083         float xi2 = float(rand()) / float(RAND_MAX);
00084         return base + xi1 * span1 + xi2 * span2;
00085 }
00086 
00087 Object* AreaLight::getObject()
00088 {
00089         return &object;
00090 }
00091 
00092 RGBColor AreaLight::getEmitted(const Vec3D& dir, const Point3D& pos) const
00093 {
00094         float cosN = dir * normal;
00095         if (cosN < std::numeric_limits<float>::epsilon()){
00096                 return 0;
00097         }
00098         // compute intensity based on the area of the light source
00099         return power * area * cosN;
00100 }
00101 
00102 
00103 void AreaLight::emitPhoton(Photon* photon) const
00104 {
00105         float xi1 = float(rand()) / float(RAND_MAX);
00106         float xi2 = float(rand()) / float(RAND_MAX);
00107         float z2 = xi2 * 2.0f * M_PI;
00108         Vec3D outDir(span1.normalized() * cos(z2) + span2.normalized() * sin(z2) * sqrt(1-xi1) + normal * sqrt(xi1));
00109         
00110         //Vec3D outDir(float(rand()) / float(RAND_MAX),
00111 //                                              float(rand()) / float(RAND_MAX),
00112 //                                              float(rand()) / float(RAND_MAX));
00113         outDir.normalize();
00114         //if(outDir * normal < 0)
00115                 //outDir = outDir * -1;
00116         
00117         photon->setDir(outDir);
00118         photon->setPos((base + span1 * xi1 + span2 * xi2)+normal*0.000001f);
00119         photon->setPower(power * area * (photon->getDir() * normal));
00120 }
00121 
00122 }

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