#include "area2.h"
#include "intersection.h"
#include "intersectionAD.h"

Spectrum AreaLightEx::eval(const Intersection &its, const Vector &d) const {
    Float tmp;
    if ( (tmp = its.shFrame.n.dot(d)) > Epsilon )
        return intensity.val*kappa.val*INV_TWOPI*std::exp(kappa.val*(tmp - 1.0f));
    else
        return Spectrum::Zero();
}

SpectrumAD AreaLightEx::evalAD(const IntersectionAD &its, const VectorAD &d) const {
    FloatAD tmp;
    if ( (tmp = its.shFrame.n.dot(d)) > Epsilon )
        return intensity*((kappa*(tmp - 1.0f)).exp()*kappa*INV_TWOPI);
    else
        return SpectrumAD();
}

Spectrum AreaLightEx::eval(const Vector &norm, const Vector &d) const {
    Float tmp;
    if ( (tmp = norm.dot(d)) > Epsilon )
        return intensity.val*kappa.val*INV_TWOPI*std::exp(kappa.val*(tmp - 1.0f));
    else
        return Spectrum::Zero();
};

SpectrumAD AreaLightEx::evalAD(const VectorAD &norm, const VectorAD &d) const {
    FloatAD tmp;
    if ( (tmp = norm.dot(d)) > Epsilon )
        return intensity*((kappa*(tmp - 1.0f)).exp()*kappa*INV_TWOPI);
    else
        return SpectrumAD();
};

Float AreaLightEx::evalDirection(const Vector& norm, const Vector& d) const {
    Float dp = norm.dot(d);
    return dp > Epsilon ? dp : 0.0f;
}

FloatAD AreaLightEx::evalDirectionAD(const VectorAD& norm, const VectorAD& d) const {
    FloatAD dp = norm.dot(d);
    return dp > Epsilon ? dp : FloatAD(0.0f);
}

Float AreaLightEx::sampleDirection(const Array2 &rnd, Vector& dir, Float *pdf) const {
     dir = squareToCosineHemisphere(Vector2(rnd[0], rnd[1]));
     if ( pdf ) *pdf = squareToCosineHemispherePdf(dir);
     return M_PI;
}
