#ifndef AKTOR_H
#define AKTOR_H

#include "MacierzGL.h"
#include "Werteks.h"

class Aktor
{
protected:
	unsigned int vao, vbo;
	unsigned int liczbaWerteksów;

private:
	void InicjujBuforWerteksów();
	void UsuńBuforWerteksów();

protected:	
	virtual unsigned int TwórzTablicęWerteksów(CWerteks*& werteksy) = 0; //obowiązki: zapełnienie tablicy werteksów, zwrócenie liczby werteksów

public:	
	Macierz4 MacierzŚwiata;
	virtual void Inicjuj(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor); //może być wywoływane w konstruktorach klas potomnych, ale nie klasy bazowej
	virtual void Rysuj();

	//materiał
	Wektor4 MateriałŚwiatłoOtoczenia;
	Wektor4 MateriałŚwiatłoRozpraszane;
	Wektor4 MateriałŚwiatłoRozbłysku;
	float MateriałWykładnikRozbłysku;

	//teksturowanie
	GLuint IndeksTekstury;
	
	Aktor();	
	virtual ~Aktor();	
};

//typedef Aktor* PAktor;

//--------------------------------------------

class AktorZBuforemIndeksów : public Aktor
{
protected:
	unsigned int liczbaIndeksów;
	unsigned int vbo_indeksy;

private:
	void InicjujBuforIndeksów();
	void UsuńBuforIndeksów();

protected:
	virtual unsigned int TwórzTablicęIndeksów(GLuint*& indeksy) = 0;

public:
	virtual void Inicjuj(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor);
	virtual void Rysuj();

	AktorZBuforemIndeksów();
	virtual ~AktorZBuforemIndeksów();
};

//--------------------------------------------

class Kwadrat : public Aktor
{
private:
	float długośćKrawędzi;
	unsigned int TwórzTablicęWerteksów(CWerteks*& werteksy);

public:
	Kwadrat(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor, float długośćKrawędzi = 2.0f);
};

class Trójkąt : public Aktor
{
private:
	float długośćPodstawy, wysokość;
	unsigned int TwórzTablicęWerteksów(CWerteks*& werteksy);

public:
	Trójkąt(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor, float długośćPodstawy = 2.0f, float wysokość = 2.0f);
};

class KwadratZBuforemIndeksów : public AktorZBuforemIndeksów
{
private:
	float długośćKrawędzi;	
	unsigned int TwórzTablicęWerteksów(CWerteks*& werteksy);
	unsigned int TwórzTablicęIndeksów(GLuint*& indeksy);

public:
	KwadratZBuforemIndeksów(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor, float długośćKrawędzi = 2.0f);
};

//--------------------------------------------

class Prostopadłościan : public Aktor
{
private:	
	float długośćKrawędziX, długośćKrawędziY, długośćKrawędziZ;
	bool koloruj;
	unsigned int TwórzTablicęWerteksów(CWerteks*& werteksy);

public:
	void Rysuj();

	Prostopadłościan(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor, float długośćKrawędziX, float długośćKrawędziY, float długośćKrawędziZ, bool koloruj);

	static Prostopadłościan* StwórzSześcian(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor, float długośćKrawędzi, bool koloruj)
	{
		return new Prostopadłościan(atrybutPołożenie, atrybutNormalna, atrybutWspółrzędneTeksturowania, atrybutKolor, długośćKrawędzi, długośćKrawędzi, długośćKrawędzi, koloruj);
	}
};


// (2) Deklaracja klasy bazowej dla aktorów złożonych z płatów.
class TeselowanyAktor : public Aktor
{
protected:
	unsigned int liczbaIndeksów;
	unsigned int vbo_indeksy;

private:
	void InicjujBuforIndeksów();
	void UsuńBuforIndeksów();

protected:
	virtual unsigned int TwórzTablicęIndeksów(GLuint*& indeksy) = 0;

public:
	virtual void Inicjuj(GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor);
	virtual void Rysuj();

	TeselowanyAktor();
	virtual ~TeselowanyAktor();
};


// (4) Deklaracja klasy sfery złożonej z płatów.
class TeselowanaSfera : public TeselowanyAktor
{
private:
	float promień;
	unsigned int liczbaSekcjiNaRównoleżnikach, liczbaSekcjiNaPołudnikach;
	unsigned int TwórzTablicęWerteksów(CWerteks*& werteksy);
	unsigned int TwórzTablicęIndeksów(GLuint*& indeksy);
	int indeks(int i, int j);

public:
	TeselowanaSfera(
		GLuint atrybutPołożenie, GLuint atrybutNormalna, GLuint atrybutWspółrzędneTeksturowania, GLuint atrybutKolor,
		float promień,
		unsigned int liczbaSekcjiNaRównoleżnikach = 20, unsigned int liczbaSekcjiNaPołudnikach = 20)
		:TeselowanyAktor(), promień(promień), liczbaSekcjiNaRównoleżnikach(liczbaSekcjiNaRównoleżnikach), liczbaSekcjiNaPołudnikach(liczbaSekcjiNaPołudnikach)
	{
		Inicjuj(atrybutPołożenie, atrybutNormalna, atrybutWspółrzędneTeksturowania, atrybutKolor);
	}
};

#endif
