// *********************************************************
// Material Class
// Author : Tamy Boubekeur (boubek@gmail.com).
// Copyright (C) 2010 Tamy Boubekeur.
// All rights reserved.
// *********************************************************

#ifndef MATERIAL_H
#define MATERIAL_H

#include <iostream>
#include <vector>

#include "Vec3D.h"
#include "Color.h"

class Scene;
struct IntersectionResult;
class Ray;

// Ce modèle suppose une couleur spéculaire blanche (1.0, 1.0, 1.0)

class Material
{
public:
    Material () :
        diffuse (0.8f),
        specular (0.2f),
        shininess(0),
        transparency(0.0),
        indice(1),
        gloss(0.0f),
        isMirror(false),
        filterGloss(false),
        color(0.5f, 0.5f, 0.5f),
        transparencyColor(1.0f,1.0f,1.0f)
    {}

    Material (float diffuse, float specular, int shininess, const Colorf& color, float gloss_=0) :
        diffuse (diffuse),
        specular (specular),
        shininess(shininess),
        transparency(0.0),
        indice(1),
        gloss(gloss_),
        isMirror(false),
        filterGloss(false),
        color (color),
        transparencyColor(1.0f,1.0f,1.0f)
    {}
    ~Material () {}

    float getDiffuse () const { return diffuse; }
    float getSpecular () const { return specular; }
    int getShininess() const { return shininess; }
    Colorf getColor () const { return color; }
    bool getIsMirror() const { return isMirror; }
    float getTransparency() const { return transparency; }
    float getIndice() const { return indice; }
    float getGloss() const { return gloss * 10.0f; }
    bool isGlossFiltered() const { return filterGloss; }
    Colorf getTransparencyColor() const { return transparencyColor; }

    void setDiffuse (float d) { diffuse = d; }
    void setSpecular (float s) { specular = s; }
    void setShininess (int s) { shininess = s; }
    void setColor (const Colorf& c) { color = c; }
    void setIsMirror(bool r) { isMirror = r; }
    void setGloss(float g) { gloss = g / 10.0f; }
    void setTransparency(float r) { transparency = r; }
    void setIndice(float n) { indice = std::max(1.0f, n); }
    void setGlossFiltered(bool v) { filterGloss = v; }
    void setTransparencyColor(Colorf c) { transparencyColor = c; }

    Colorf brdfAt(const Ray& ray, const IntersectionResult& intersection, const Scene& scene, unsigned int depth) const;
    Colorf pathTracedBrdfAt(const Ray& ray, const IntersectionResult& intersection, const Scene& scene, unsigned int depth) const;

private:
    Colorf getPhongDiffuse(const Vec3Df& normal, const IntersectionResult& intersection, const Scene& scene) const;
    Colorf getTransparent(const Vec3Df& incident, const IntersectionResult& intersection, const Scene& scene, unsigned int depth) const;
    Vec3Df addGloss(const Vec3Df& dir, const Vec3Df& baseGen) const;
    Vec3Df reflect(const Vec3Df& v, const Vec3Df& normal) const;
    Vec3Df refract(const Vec3Df& v, const Vec3Df& normal, float n1, float n2, bool& success) const;
    float reflectionRatio(const Vec3Df& v, const Vec3Df& normal, float n1, float n2) const;

private:
    float diffuse;
    float specular;
    int shininess;
    float transparency;
    float indice;
    float gloss;
    bool isMirror;
    bool filterGloss;
    Colorf color;
    Colorf transparencyColor;
};

#endif // MATERIAL_H

// Some Emacs-Hints -- please don't remove:
//
//  Local Variables:
//  mode:C++
//  tab-width:4
//  End:
