#include "Kwadryka.h"

unsigned int Kwadryka::TwórzTablicęWerteksówŚciętegoStożka(CWerteks*& tablicaWerteksów, float promieńDolny, float promieńGórny, float położeniePodstawy, float wysokość, int liczbaSekcji)
{
	const int liczbaWerteksów = 2 * (liczbaSekcji + 1);
	const double przyrostKąta = 2 * M_PI / liczbaSekcji;
	const float r = 1, g = 1, b = 1, a = 1;

	tablicaWerteksów = new CWerteks[liczbaWerteksów];	

	for (int i = 0; i <= liczbaSekcji; i++) //ilość par musi być większa o 1 niż ilość sekcji, przy pełnym obrocie pierwsza i ostatnia są takie same
	{		
		double kąt = i * przyrostKąta;

		tablicaWerteksów[2 * i].x = promieńGórny*(float)cos(kąt);
		tablicaWerteksów[2 * i].y = promieńGórny*(float)sin(kąt);
		tablicaWerteksów[2 * i].z = położeniePodstawy + wysokość;
		tablicaWerteksów[2 * i].r = r;
		tablicaWerteksów[2 * i].g = g;
		tablicaWerteksów[2 * i].b = b;
		tablicaWerteksów[2 * i].a = a;

		tablicaWerteksów[2 * i + 1].x = promieńDolny*(float)cos(kąt);
		tablicaWerteksów[2 * i + 1].y = promieńDolny*(float)sin(kąt);
		tablicaWerteksów[2 * i + 1].z = położeniePodstawy;
		tablicaWerteksów[2 * i + 1].r = r;
		tablicaWerteksów[2 * i + 1].g = g;
		tablicaWerteksów[2 * i + 1].b = b;
		tablicaWerteksów[2 * i + 1].a = a;

		//obliczanie normalnej
		float a = promieńDolny - promieńGórny;
		float c = sqrt(a * a + wysokość * wysokość);
		float sinTheta = a / c;
		float cosTheta = wysokość / c;
		tablicaWerteksów[2 * i].nx = cos(kąt)*cosTheta;
		tablicaWerteksów[2 * i].ny = sin(kąt)*cosTheta;
		tablicaWerteksów[2 * i].nz = sinTheta;
		tablicaWerteksów[2 * i + 1].nx = tablicaWerteksów[2 * i].nx;
		tablicaWerteksów[2 * i + 1].ny = tablicaWerteksów[2 * i].ny;
		tablicaWerteksów[2 * i + 1].nz = tablicaWerteksów[2 * i].nz;

		//współrzędne teskturowania
		tablicaWerteksów[2 * i].s = 1 - kąt / 2 / M_PI;
		tablicaWerteksów[2 * i].t = 0;
		tablicaWerteksów[2 * i + 1].s = 1 - kąt / 2 / M_PI;
		tablicaWerteksów[2 * i + 1].t = 1;
	}

	return liczbaWerteksów;
}

unsigned int Kwadryka::TwórzTablicęWerteksów(CWerteks*& werteksy)
{
	if (liczbaPasm == 1)
	{
		return TwórzTablicęWerteksówŚciętegoStożka(werteksy, promieńDolny, promieńGórny, położeniePodstawy, wysokość, liczbaSekcji);
	}
	else //tylko sfera ma więcej niż jedno pasmo; tu lepiej byłoby użyć bufora indeksów
	{
		unsigned int całkowitaLiczbaWerteksów = liczbaWerteksówWPaśmie * liczbaPasm;
		const float promień = promieńDolny;
		werteksy = new CWerteks[całkowitaLiczbaWerteksów];

		double przyrostKątaTheta = M_PI / liczbaPasm;
		for (int i = 0; i < liczbaPasm; i++)
		{
			double kątThetaGórny = i * przyrostKątaTheta;
			double kątThetaDolny = (i + 1) * przyrostKątaTheta;
			float wysokośćGórna = (float)(promień * cos(kątThetaGórny));
			float wysokośćDolna = (float)(promień * cos(kątThetaDolny));
			float _promieńGórny = (float)(promień * sin(kątThetaGórny));
			float _promieńDolny = (float)(promień * sin(kątThetaDolny));

			CWerteks* tablicaWerteksówPasma;
			unsigned int liczbaWerteksówWPaśmie = TwórzTablicęWerteksówŚciętegoStożka(
				tablicaWerteksówPasma, _promieńDolny, _promieńGórny, wysokośćDolna, wysokośćGórna - wysokośćDolna, liczbaSekcji);
			CWerteks* początekWerteksówPasma = werteksy + liczbaWerteksówWPaśmie * i;
			std::copy(tablicaWerteksówPasma, tablicaWerteksówPasma + liczbaWerteksówWPaśmie, początekWerteksówPasma);
			delete[] tablicaWerteksówPasma;
		}

		return całkowitaLiczbaWerteksów;
	}
}

void Kwadryka::Rysuj()
{
	glBindVertexArray(vao);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	for (int i = 0; i < liczbaPasm; ++i)
	{
		glDrawArrays(GL_TRIANGLE_STRIP, i*liczbaWerteksówWPaśmie, liczbaWerteksówWPaśmie);
	}
	//glBindBuffer(GL_ARRAY_BUFFER, NULL);
	//glBindVertexArray(NULL);
}

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

unsigned int SferaZBuforemIndeksów::TwórzTablicęWerteksów(CWerteks*& werteksy)
{
	const unsigned int całkowitaLiczbaWerteksów = liczbaSekcjiNaRównoleżnikach * (liczbaSekcjiNaPołudnikach - 1) + 2;
	werteksy = new CWerteks[całkowitaLiczbaWerteksów];

	const double przyrostKątaTheta = M_PI / liczbaSekcjiNaPołudnikach;
	const double przyrostKątaPhi = 2 * M_PI / liczbaSekcjiNaRównoleżnikach;

	const float r = 1, g = 1, b = 1, a = 1;

	for (unsigned int i = 1; i < liczbaSekcjiNaPołudnikach; i++) //tu zmiany
	{
		double kątTheta = i * przyrostKątaTheta;
		float _wysokość = (float)(promień * cos(kątTheta));
		float _promień = (float)(promień * sin(kątTheta));

		for (unsigned int j = 0; j < liczbaSekcjiNaRównoleżnikach; j++)
		{
			double kątPhi = j*przyrostKątaPhi;
			unsigned int indeks = 1 + j + (i - 1)*liczbaSekcjiNaRównoleżnikach;

			werteksy[indeks].x = _promień*(float)cos(kątPhi);
			werteksy[indeks].y = _promień*(float)sin(kątPhi);
			werteksy[indeks].z = _wysokość;
			werteksy[indeks].nx = werteksy[indeks].x / _promień;
			werteksy[indeks].ny = werteksy[indeks].y / _promień;
			werteksy[indeks].nz = werteksy[indeks].z / _promień;
			werteksy[indeks].s = 1 - (float) kątPhi / 2 / M_PI;
			werteksy[indeks].t = kątTheta / M_PI;
			werteksy[indeks].r = r;
			werteksy[indeks].g = g;
			werteksy[indeks].b = b;
			werteksy[indeks].a = 1;
		}
	}
	//biegun =z
	werteksy[0].x = 0;
	werteksy[0].y = 0;
	werteksy[0].z = promień;
	werteksy[0].nx = 0;
	werteksy[0].ny = 0;
	werteksy[0].nz = 1;
	werteksy[0].s = 0;
	werteksy[0].t = 0;
	werteksy[0].r = r;
	werteksy[0].g = g;
	werteksy[0].b = b;
	//biegun =z
	unsigned int _indeks = 1 + (liczbaSekcjiNaPołudnikach - 1)*liczbaSekcjiNaRównoleżnikach;
	werteksy[_indeks].x = 0;
	werteksy[_indeks].y = 0;
	werteksy[_indeks].z = -promień;
	werteksy[_indeks].nx = 0;
	werteksy[_indeks].ny = 0;
	werteksy[_indeks].nz = -1;
	werteksy[_indeks].s = 1;
	werteksy[_indeks].t = 1;
	werteksy[_indeks].r = r;
	werteksy[_indeks].g = g;
	werteksy[_indeks].b = b;

	return całkowitaLiczbaWerteksów;
}

unsigned int SferaZBuforemIndeksów::TwórzTablicęIndeksów(GLuint*& indeksy)
{
	const unsigned int liczbaIndeksówWPaśmie = 2 * (liczbaSekcjiNaRównoleżnikach + 1);
	const unsigned int całkowitaLiczbaIndeksów = liczbaIndeksówWPaśmie * liczbaSekcjiNaPołudnikach;
	indeksy = new GLuint[całkowitaLiczbaIndeksów];

	for (unsigned int i = 0; i < liczbaSekcjiNaPołudnikach; i++)
	{
		for (unsigned int j = 0; j < liczbaSekcjiNaRównoleżnikach; j++)
		{
			unsigned int _indeks = j + i*(liczbaSekcjiNaRównoleżnikach + 1);
			indeksy[2 * _indeks] = (i == 0) ? 0 : (1 + j + (i - 1)*liczbaSekcjiNaRównoleżnikach);
			indeksy[2 * _indeks + 1] = (i == liczbaSekcjiNaPołudnikach - 1) ? (liczbaWerteksów - 1) : (1 + j + i*liczbaSekcjiNaRównoleżnikach);
		}
		unsigned int _indeks = liczbaSekcjiNaRównoleżnikach + i*(liczbaSekcjiNaRównoleżnikach + 1);
		indeksy[2 * _indeks] = (i == 0) ? 0 : (i*liczbaSekcjiNaRównoleżnikach);
		indeksy[2 * _indeks + 1] = (i == liczbaSekcjiNaPołudnikach - 1) ? (liczbaWerteksów - 1) : (indeksy[2 * _indeks] + liczbaSekcjiNaRównoleżnikach);
	}

	return całkowitaLiczbaIndeksów;
}