#include "diffuse.h"
#include "intersection.h"
#include "intersectionAD.h"
#include "utils.h"
#include <assert.h>

Spectrum DiffuseBSDF::eval(const Intersection &its, const Vector &wo, EBSDFMode mode) const {
    if (its.wi.z() < Epsilon || wo.z() < Epsilon)
        return Spectrum::Zero();
    else {
        if (mode == EBSDFMode::EImportanceWithCorrection)
            return reflectance.val*INV_PI*wo.z() * correction(its, wo);
        else
            return reflectance.val*INV_PI*wo.z();
    }
}


SpectrumAD DiffuseBSDF::evalAD(const IntersectionAD &its, const VectorAD &wo, EBSDFMode mode) const {
    if (its.wi.z() < Epsilon || wo.z() < Epsilon)
        return SpectrumAD();
    else {
        if (mode == EBSDFMode::EImportanceWithCorrection)
            return reflectance*INV_PI*wo.z()*correctionAD(its, wo);
        else
            return reflectance*INV_PI*wo.z();
    }
}


Spectrum DiffuseBSDF::sample(const Intersection &its, const Array3 &rnd, Vector &wo, Float &pdf, Float &eta, EBSDFMode mode) const {
    if (its.wi.z() < Epsilon)
        return Spectrum::Zero();
    wo = squareToCosineHemisphere(Vector2(rnd[0], rnd[1]));
    eta = 1.0f;
    pdf = squareToCosineHemispherePdf(wo);
    if  (mode == EBSDFMode::EImportanceWithCorrection)
        return reflectance.val * correction(its, wo);
    else
        return reflectance.val;
}


Float DiffuseBSDF::pdf(const Intersection &its, const Vector &wo) const{
    if (its.wi.z() < Epsilon || wo.z() < Epsilon)
        return 0.0;
    else
        return squareToCosineHemispherePdf(wo);
}
