/*
 * PBrtJ -- Port of pbrt v3 to Java.
 * Copyright (c) 2017 Rick Weyrauch.
 *
 * pbrt source code is Copyright(c) 1998-2016
 * Matt Pharr, Greg Humphreys, and Wenzel Jakob.
 *
 */

package org.pbrt.core;

public class MicrofacetReflection extends BxDF {

    public MicrofacetReflection(Spectrum R, MicrofacetDistribution distribution, Fresnel fresnel) {
        super(BSDF_REFLECTION | BSDF_GLOSSY);
        this.R = new Spectrum(R);
        this.distribution = distribution;
        this.fresnel = fresnel;
    }

    @Override
    public Spectrum f(Vector3f wo, Vector3f wi) {
        float cosThetaO = Reflection.AbsCosTheta(wo), cosThetaI = Reflection.AbsCosTheta(wi);
        Vector3f wh = wi.add(wo);
        // Handle degenerate cases for microfacet reflection
        if (cosThetaI == 0 || cosThetaO == 0) return new Spectrum(0);
        if (wh.x == 0 && wh.y == 0 && wh.z == 0) return new Spectrum(0);
        wh = Vector3f.Normalize(wh);
        Spectrum F = fresnel.Evaluate(Vector3f.Dot(wi, wh));
        return R.scale(distribution.D(wh) * distribution.G(wo, wi)).multiply(F.scale(1 / (4 * cosThetaI * cosThetaO)));
    }

    @Override
    public String toString() {
        return "[ MicrofacetReflection R: " + R.toString() + " distribution: " + distribution.toString() +
                " fresnel: " + fresnel.toString() + " ]";
    }

    private final Spectrum R;
    private final MicrofacetDistribution distribution;
    private final Fresnel fresnel;
}
@@ -1124,32 +1124,996 @@
 etaO)));%0A    %7D%0A%0A
+    @Override%0A    public BxDFSample Sample_f(Vector3f wo, Point2f u) %7B%0A        BxDFSample bs = new BxDFSample();%0A        bs.f = new Spectrum(0);%0A        bs.pdf = 0.0f;%0A        bs.wiWorld = new Vector3f();%0A        bs.sampledType = BSDF_NONE;%0A%0A        // Sample microfacet orientation $%5Cwh$ and reflected direction $%5Cwi$%0A        if (wo.z == 0) return bs;%0A        Vector3f wh = distribution.Sample_wh(wo, u);%0A        bs.wiWorld = Reflection.Reflect(wo, wh);%0A        if (!Reflection.SameHemisphere(wo, bs.wiWorld)) return bs;%0A%0A        // Compute PDF of _wi_ for microfacet reflection%0A        bs.pdf = distribution.Pdf(wo, wh) / (4 * Vector3f.Dot(wo, wh));%0A        bs.f = f(wo, bs.wiWorld);%0A        return bs;%0A    %7D%0A%0A    @Override%0A    public float Pdf(Vector3f wo, Vector3f wi) %7B%0A        if (!Reflection.SameHemisphere(wo, wi)) return 0;%0A        Vector3f wh = Vector3f.Normalize(wo.add(wi));%0A        return distribution.Pdf(wo, wh) / (4 * Vector3f.Dot(wo, wh));%0A    %7D%0A%0A
     @Override%0A  

Implement missing functions.