00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "light.h"
00026 #include "primitive.h"
00027
00028 AreaLight::AreaLight(const Transform &light2world,
00029 const Spectrum &le, int ns,
00030 const Reference<Shape> &s)
00031 : Light(light2world, ns) {
00032 Lemit = le;
00033 if (s->CanIntersect())
00034 shape = s;
00035 else {
00036
00037 Reference<Shape> shapeSet = s;
00038 vector<Reference<Shape> > todo, done;
00039 todo.push_back(shapeSet);
00040 while (todo.size()) {
00041 Reference<Shape> sh = todo.back();
00042 todo.pop_back();
00043 if (sh->CanIntersect())
00044 done.push_back(sh);
00045 else
00046 sh->Refine(todo);
00047 }
00048 if (done.size() == 1) shape = done[0];
00049 else {
00050 if (done.size() > 16)
00051 Warning("Area light geometry turned into %d shapes; "
00052 "may be very inefficient.", (int)done.size());
00053 shape = new ShapeSet(done, s->ObjectToWorld, s->reverseOrientation);
00054 }
00055 }
00056 area = shape->Area();
00057 }
00058 Spectrum AreaLight::Sample_L(const Point &p,
00059 const Normal &n, float u1, float u2,
00060 Vector *wi, float *pdf,
00061 VisibilityTester *visibility) const {
00062 Normal ns;
00063 Point ps = shape->Sample(p, u1, u2, &ns);
00064 *wi = Normalize(ps - p);
00065 *pdf = shape->Pdf(p, *wi);
00066 visibility->SetSegment(p, ps);
00067 return L(ps, ns, -*wi);
00068 }
00069 float AreaLight::Pdf(const Point &p, const Normal &N,
00070 const Vector &wi) const {
00071 return shape->Pdf(p, wi);
00072 }
00073 Spectrum AreaLight::Sample_L(const Point &P,
00074 float u1, float u2, Vector *wo, float *pdf,
00075 VisibilityTester *visibility) const {
00076 Normal Ns;
00077 Point Ps = shape->Sample(P, u1, u2, &Ns);
00078 *wo = Normalize(Ps - P);
00079 *pdf = shape->Pdf(P, *wo);
00080 visibility->SetSegment(P, Ps);
00081 return L(Ps, Ns, -*wo);
00082 }
00083 Spectrum AreaLight::Sample_L(const Scene *scene, float u1,
00084 float u2, float u3, float u4,
00085 Ray *ray, float *pdf) const {
00086 Normal ns;
00087 ray->o = shape->Sample(u1, u2, &ns);
00088 ray->d = UniformSampleSphere(u3, u4);
00089 if (Dot(ray->d, ns) < 0.) ray->d *= -1;
00090 *pdf = shape->Pdf(ray->o) * INV_TWOPI;
00091 return L(ray->o, ns, ray->d);
00092 }
00093 float AreaLight::Pdf(const Point &P, const Vector &w) const {
00094 return shape->Pdf(P, w);
00095 }
00096 Spectrum AreaLight::Sample_L(const Point &P, Vector *wo,
00097 VisibilityTester *visibility) const {
00098 Normal Ns;
00099 Point Ps = shape->Sample(P, RandomFloat(), RandomFloat(), &Ns);
00100 *wo = Normalize(Ps - P);
00101 visibility->SetSegment(P, Ps);
00102 float pdf = shape->Pdf(P, *wo);
00103 if (pdf == 0.f) return Spectrum(0.f);
00104 return L(P, Ns, -*wo) / pdf;
00105 }
00106 extern "C" DLLEXPORT Light *CreateAreaLight(const Transform &light2world, const ParamSet ¶mSet,
00107 const Reference<Shape> &shape) {
00108 Spectrum L = paramSet.FindOneSpectrum("L", Spectrum(1.0));
00109 int nSamples = paramSet.FindOneInt("nsamples", 1);
00110 return new AreaLight(light2world, L, nSamples, shape);
00111 }