//---------------------------------------------------------------------------
#ifndef obrazH
#define obrazH

#include "skala.h"
#include "geometria.h"
#include "3d.h"                  //do uruchamiania (wizualizacja TPromien::pokaz())

#include <vector>

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//  Definicja współczynnika odbicia światła - cechy trójkątów.
//  Duże Ar - duże odbicie czerwieni, itd dla Ag, Ab
class TOdbicie
{
 private:
 public:
    double r, g, b;             //ułamkowe faktory pochłaniania
    TOdbicie();                 //inicjuje na pełne odbicie
    TOdbicie( double Ar, double Ag, double Ab);
    TOdbicie( const TOdbicie &o);
    TOdbicie & operator= (const TOdbicie &o);
};
//---------------------------------------------------------------------------
//  Definicja koloru powierzchni i koloru niesionego przez promien.
class TSwiatlo
{
 private:
 public:
    double r, g, b;
    TSwiatlo();                   //inicjuje na czerń
    TSwiatlo( double Ar, double Ag, double Ab);
    TSwiatlo( const TSwiatlo &i);
    TSwiatlo & operator= (const TSwiatlo &);
    TSwiatlo & operator+= (const TSwiatlo &);
    void odbij( TOdbicie o);  //zmniejsza światło czynnikiem o
    TColor daj_kolor( double procent);
};
//---------------------------------------------------------------------------
//  Definicja elementu zabudowy sceny
class TTrojkat
{
 private:
 public:
    TPunkt p1, p2, p3;          //punkty wyznaczające trójkąt
    TWektor N;                  //wektor normalny
    TSwiatlo swiatlo;           //gdy trójkąt jest źródłem światła
    TOdbicie odbicie;           //gdy trójkąt pochłania światło odbite
    TTrojkat( void);            //konstruktor domyślny
    TTrojkat( TPunkt Ap1, TPunkt Ap2, TPunkt Ap3, TSwiatlo Ai, TOdbicie Ao);
    TTrojkat( const TTrojkat &t);
    TTrojkat & operator= (const TTrojkat &t);
};
//---------------------------------------------------------------------------
//  Definicja promienia
class TPromien
{
 private:
    bool czy_trafia_w_plaszczyzne( TTrojkat t, TPunkt &p);
 public:
    TPunkt r0;              //punkt zaczepienia
    TWektor kierunek;       //skierowanie, zadane wektorem (unormowanym)
    TSwiatlo swiatlo;       //inicjowane na czerń, a potem - zależnie od trafień
    TPromien( void);
    TPromien( TPunkt Aa, TPunkt Ab);
    TPromien( TPunkt Aa, TWektor Akierunek);
    TPromien( const TPromien &p);
    TPromien & operator= (const TPromien &);
    bool czy_trafia_w_trojkat( TTrojkat t, TPunkt &p);
    void odbij( TTrojkat t, TPunkt p);

    void pokaz( TPunkt koniec, T3d *d, TCanvas *cnv, TColor kolor);
};
//---------------------------------------------------------------------------
//  Scena jest zabudowana wyłącznie trójkątami.
class TScena
{
 private:
 public:
	std::vector <TTrojkat> trojkaty;
    int il() { return (int)trojkaty.size();}
    TScena( void);
    void dodaj_trojkat( TTrojkat t);
};
//---------------------------------------------------------------------------
//  Ray Tracing z podglądem z boku za pomocą T3d
class TObraz : public TSkalowanie
{
 private:
    TPunkt obs;             //pozycja obserwatora
    double R, Rxy;          //odległość obserwatora i jej rzut na płaszczyznę XY
    double odl_ekr;         //odległość ekranu od oczu
    TScena *scena;
    int glebokosc_rekurencji;

    T3d *projekcja;
    TCanvas *cnv;
    bool pokazuj_linie;

    double sf, cf, st, ct;  //współczynniki macierzy obrotu
    TPromien inicjuj_promien( int i, int j);//promien, przechodzący przez piksel (i, j);
    bool w_droge( TPromien &r, int nr_odbicia);
    bool daj_najblizszy_trafiony_trojkat( TPromien r, TTrojkat &t, TPunkt &p);
 public:
    TObraz( TPunkt Aobs,      //pozycja obserwatora
            int eszer, int ewys,//pikselowe pole obrazu
            double Aodl_ekr,    //odległość pola obrazu
            double szer, double wys, TScena *Ascena,//fizyczne pole obrazu
            int Aglebokosc_rekurencji,
            T3d *Aprojekcja, TCanvas *Acnv, bool Apokazuj_linie);
    TColor kolor_piksela( int i, int j, int jasn_proc);
    TPunkt daj_punkt( int i, int j);//funkcja testowa, dająca obraz piksela (i, j);

};
//---------------------------------------------------------------------------
//  Funkcja pomocnicza. Maksimum wartości bezwzględnych.
inline double max( double a, double b, double c)
{
 double a1 = a < 0 ? -a : a,
        b1 = b < 0 ? -b : b,
        c1 = c < 0 ? -c : c;

 return (a1 > b1 ? (a1 > c1 ? a : c) : (b1 > c1 ? b : c));
}
#endif
