00001 #ifndef AREALIGHT_H_
00002 #define AREALIGHT_H_
00003
00004 #include "Light.h"
00005 #include "../primitives/AABB.h"
00006 #include "../primitives/Triangle.h"
00007 #include "../objects/AffineObject.h"
00008 #include "../materials/LightMaterial.h"
00009
00010 namespace rcrt
00011 {
00012
00013 class AreaLight : public rcrt::Light
00014 {
00015 friend class AreaLightSampler;
00016
00017 protected:
00018 Point3D base;
00019 Vec3D span1;
00020 Vec3D span2;
00021 Vec3D normal;
00022 float area;
00023 AffineObject object;
00024 LightMaterial material;
00025 Triangle tri1;
00026 Triangle tri2;
00027 std::vector<Primitive*> triList;
00028 float aspect;
00029
00030
00031 Point3D getRandomPosition() const;
00032 LightSample getSample(const Point3D& p, const Vec3D& no, const Point3D& pos, Scene* s = 0) const;
00033 LightSample getSample(const Point2D& uv, const Vec3D& no, const Point3D& pos, Scene* s = 0) const;
00034
00035 public:
00036 AreaLight(const RGBColor& p, const Point3D& pos,
00037 const Vec3D& dir1, const Vec3D& dir2, const Vec3D& no = Vec3D(0));
00038 virtual ~AreaLight();
00039
00040
00041 virtual LightSample illuminate(const Point3D& p, const Vec3D& no) const;
00042 virtual void illuminate(const Point3D& p, const Vec3D& no, std::vector<LightSample>& samples,
00043 const int& noSamples, Scene* s = 0 ) const;
00044 virtual RGBColor getEmitted(const Vec3D& dir, const Point3D& pos) const;
00045
00046 virtual Object* getObject();
00047
00048 virtual void emitPhoton(Photon* photon) const;
00049 };
00050
00051 inline LightSample AreaLight::getSample(const Point3D& p, const Vec3D& no,
00052 const Point3D& loc, Scene* s) const
00053 {
00054 Vec3D dir(loc-p);
00055 if(s != 0 && s->castShadows()){
00056 if(s->isOccluded(p, dir.normalized(), dir.norm()))
00057 return LightSample(0,0,0,0);
00058 }
00059
00060 float length = dir.norm();
00061 dir.normalize();
00062
00063 float att = 1.0f / (length * length);
00064
00065
00066 float cosN = -(dir * normal);
00067 if (cosN < std::numeric_limits<float>::epsilon()){
00068 return LightSample(0,0,0,0);
00069 }
00070
00071 return LightSample(1,dir, length, power * att * area * cosN);
00072 }
00073
00074 inline LightSample AreaLight::getSample(const Point2D& uv, const Vec3D& no,
00075 const Point3D& p, Scene* s) const
00076 {
00077 return getSample(p, no, base+uv.x()*span1+uv.y()*span2, s);
00078 }
00079
00080 }
00081
00082 #endif