//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "stereo.h"
#include "fscenauporzadkowana.h"
#include <stdlib.h>
#include <math.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
//	Wirtualny przedmiot
//---------------------------------------------------------------------------
//  Konstruktor przyjmuje do wiadomości położenie i rozmiar przedmiotu
TPrzedmiot :: TPrzedmiot( TPunkt Ap0, double Abok)
{
 bok = Abok;
 p0 = Ap0;
 r = 0;
}
//---------------------------------------------------------------------------
//  Konstruktor kopiujący
TPrzedmiot :: TPrzedmiot( const TPrzedmiot &przedm)
{
 bok = przedm.bok;
 p0 = przedm.p0;
 r = przedm.r;
}
//---------------------------------------------------------------------------
//  Operator przypisania
TPrzedmiot & TPrzedmiot :: operator= (const TPrzedmiot &przedm)
{
 if( this != &przedm)
 {
    bok = przedm.bok;
    p0 = przedm.p0;
    r = przedm.r;
 }
 return *this;
}
//---------------------------------------------------------------------------
//	Operator niezbędny do sortowania
bool TPrzedmiot :: operator < (const TPrzedmiot &przedm) const
{
 return (r > przedm.r);
}
//---------------------------------------------------------------------------
//  Obliczenie odległości przedmiotu od obserwatora.
//  Jako reprezentatywny punkt przedmiotu przyjmujemy jego środek
void TPrzedmiot :: dystans( TPunkt obserwator)
{
 r = sqrt((p0.x-obserwator.x) * (p0.x-obserwator.x));
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
 inicjuj_scene();
 odczytaj_parametry();
}
//---------------------------------------------------------------------------
//  Utworzenie zbioru przedmiotów, tutaj kwadratowych płytek
void TForm1 :: inicjuj_scene( void)
{
 int i, il_przedmiotow = 10;
 TPunkt p0;                         //środek płytki
 double bok = 3;                    //rozmiar płytki
 for( i = 0; i < il_przedmiotow; i ++)
 {
    p0 = TPunkt( 5-random( 10), 5-random( 10), 5-random( 10));
    przedmioty.insert( przedmioty.end(), TPrzedmiot( p0, bok));
 }
}
//---------------------------------------------------------------------------
// Odczytaj parametry
void TForm1 :: odczytaj_parametry( void)
{
 try
 {
    sp = (StylPatrzenia)RadioGroup1 -> ItemIndex;
    if( sp == Anaglif)          //dla okularów kolor linii = kolor wypełnienia
    {
        Lkolor1 = Lkolor2 = clRed;
        Rkolor1 = Rkolor2 = clAqua;
    }
    else
    {
        Lkolor1 = Rkolor1 = clBlack;
        Lkolor2 = Rkolor2 = clYellow;
    }
    baza = (double)TrackBar1 -> Position / 100.;
    obserwator.x = (double)TrackBar2 -> Position / 10.;
    obserwator.y = (double)TrackBar3 -> Position / 10.;
    obserwator.z = (double)TrackBar4 -> Position / 10.;
    ogniskowa = (double)TrackBar5 -> Position/100.;
 }
 catch(...)
 {
 }
}
//---------------------------------------------------------------------------
//  Wymierzenie odległości przedmiot - obserwator i posortowanie przedmiotów
void TForm1 :: uporzadkuj_scene( void)
{
 for( int i = 0; i < (int)przedmioty.size(); i ++)
 {
    przedmioty[ i].dystans( obserwator);
 }
 std::sort( przedmioty.begin(), przedmioty.end());
}
//---------------------------------------------------------------------------
//  Wykreślenie przedmiotów
void TForm1 :: renderuj_scene( TStereo *s)
{
 for( int i = 0; i < (int)przedmioty.size(); i ++)
 {
    plytka( s, przedmioty[ i].p0, przedmioty[ i].bok);
 }
}
//---------------------------------------------------------------------------
//  Płytka o środku w 'p' i krawędzi 'bok', widziana w projekcji 's'
void TForm1 :: plytka( TStereo *s, TPunkt p, double bok)
{
 double b = bok/2;
 TPunkt p1(p.x+b,p.y+b,p.z), p2(p.x-b,p.y+b,p.z), p3(p.x-b,p.y-b,p.z), p4(p.x+b,p.y-b,p.z);

 s -> czworokat_stereo( p1, p2, p3, p4, Lkolor1, Rkolor1, Lkolor2, Rkolor2);
}
//---------------------------------------------------------------------------
//  Wykreślenie kostki, rozpiętej na podanych wierzchołkach
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
 TStereo s( obserwator,         //pozycja obserwatora
    0, 0, PaintBox1 -> Width, PaintBox1 -> Height, //okienko ekranowe
    baza,                       //odległość między oczami
    PaintBox1 -> Canvas,        //aparat graficzny
    sp,                         //styl projekcji stereo
    ogniskowa);                 //odległość oka od płaszczyzny obrazowej

 uporzadkuj_scene();
 renderuj_scene( &s);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
 odczytaj_parametry();
 PaintBox1 -> Refresh();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)
{
 if( Key == VK_ESCAPE)
    Close();
}
//---------------------------------------------------------------------------

