/**
 *
 * \file	horizont.cc
 *
 * \brief Code for the Horizont class.
 *
 * \author	MAxx Headroom
 * \version	0.0
 * \date	25.01.2004 13:32:35
 *
 **/


#include "stdafx.h"
#include "horizont.h"
#include <math.h>


//{{{ Horizont::Horizont(Texture* t)
Horizont::Horizont()
:
	tex(0),
	radius(HOR_DEFAULT_R),
	segments(HOR_DEFAULT_SEG)
{
	init();
} /* Horizont::Horizont(Texture* t) */
//}}}


//{{{ Horizont::Horizont(Texture* t)
Horizont::Horizont(Texture* t)
:
	tex(t),
	radius(HOR_DEFAULT_R),
	segments(HOR_DEFAULT_SEG)
{
	init();
} /* Horizont::Horizont(Texture* t) */
//}}}


//{{{ Horizont::Horizont(Texture* t, int seg)
Horizont::Horizont(Texture* t, int seg)
:
	tex(t),
	radius(HOR_DEFAULT_R),
	segments(seg),
	pos(0.0, 0.0, 0.0)
{
	init();
} /* Horizont::Horizont(Texture* t, int seg) */
//}}}


//{{{ Horizont::Horizont(Texture* t, float dia)
Horizont::Horizont(Texture* t, float r)
:
	tex(t),
	radius(r),
	segments(HOR_DEFAULT_SEG),
	pos(0.0, 0.0, 0.0)
{
	init();
} /* Horizont::Horizont(Texture* t, float dia) */
//}}}


//{{{ Horizont::Horizont(Texture* t, float dia, int seg)
Horizont::Horizont(Texture* t, float r, int seg)
:
	tex(t),
	radius(r),
	segments(seg),
	pos(0.0, 0.0, 0.0)
{
	init();
} /* Horizont::Horizont(Texture* t, float dia, int seg) */
//}}}


//{{{ Horizont::Horizont(Texture* t, float dia, int seg, vectorf p)
Horizont::Horizont(Texture* t, float r, int seg, vectorf p)
:
	tex(t),
	radius(r),
	segments(seg),
	pos(p)
{
	init();
} /* Horizont::Horizont(Texture* t, float dia, int seg, vectorf p) */
//}}}


//{{{ virtual Horizont::~Horizont()
Horizont::~Horizont()
{
	delete tex;
	if (points) delete [] points;
	if (texPoints) delete [] texPoints;
	if (idxStrip1) delete [] idxStrip1;
	if (idxStrip2) delete [] idxStrip2;
	if (idxFan) delete [] idxFan;

} /* virtual Horizont::~Horizont() */
//}}}



//{{{ void Horizont::init()
bool Horizont::init()
{
	int numPoints = (segments+1) * 3 + 1;
	int numIdxStrip = (segments+1) * 2;
				//   +------------+-------> for a complete strip we need one more point
				//                  +-+---> two time the points give one strip
	int numIdxFan = (segments+1) + 1;
				// +------------+---------> number of points on the base
				//                +-+-----> one point at the top

	////////////////////////////////////////////////////////////////////////////
	// Init arrays:
	points = new GLfloat[numPoints*3];
	texPoints = new GLfloat[numPoints*2];
	idxStrip1 = new GLuint[numIdxStrip+1];
	idxStrip2 = new GLuint[numIdxStrip+1];
	idxFan = new GLuint[numIdxFan];

	////////////////////////////////////////////////////////////////////////////
	// Init points:
	int i=0;
	int level=0;
	float angle = 2*(float)M_PI / (float)segments;
	float r;			// actual radius
	float x, y, z;
	float tx, ty;		// Texture coordinates
	float tstrt, tstp;	// Texture key data
	
	for(; level<3; ++level) {
		switch (level) {
			case 0:
				y = 0.0f;
				ty = 0.001f;
				tstrt = 0.0f;
				break;
			case 1:
				y = radius*HOR_LEVEL1;
				ty = HOR_LEVEL1;
				tstrt = 0.0f;
				break;
			case 2:
				y = radius*HOR_LEVEL2;
				ty = HOR_LEVEL2;
				tstrt = 0.2f;
				break;
		}
		float ay = 0.0f;		// angle arround the y-axis.
		r = sqrt(radius*radius - y*y);
		x = r;
		z = 0.0f;
		tstp = (1.0f - 2.0f*tstrt)/(float)segments;
		tx = tstrt;

		for(int j=0; j<segments+1; ++j) {
			points[i*3] = x;
			points[i*3+1] = y;
			points[i*3+2] = z;
			ay += angle;
			x = r*cos(ay);
			z = -r*sin(ay);		// this is, why the points run counter clockwise
			texPoints[i*2] = tx;
			texPoints[i*2+1] = ty;
			tx += tstp;
			++i;
		}
	}

	// Top point:
	points[i*3] = 0.0f;
	points[i*3+1] = radius;
	points[i*3+2] = 0.0f;
	texPoints[i*2] = 0.5f;
	texPoints[i*2+1] = 1.0f;

	////////////////////////////////////////////////////////////////////////////
	// init indizes:
	// strips:
	for(i=0; i<(segments+1); ++i) {
		idxStrip1[i*2] = i+(segments+1);
		idxStrip1[i*2+1] = i;
		idxStrip2[i*2] = i+((segments+1)*2);
		idxStrip2[i*2+1] = i+(segments+1);
	}
	/*
	idxStrip1[i*2] = segments;
	idxStrip1[i*2+1] = 0;
	idxStrip2[i*2] = segments*2;
	idxStrip2[i*2+1] = segments;
	*/
	// fan:
	idxFan[0] = (segments+1)*3;
	for(i=1; i<segments+2; ++i) {
		idxFan[i] = ((segments+1)*2 - 1) + i;
	}
	//idxFan[i] = segments*2;

	return true;
} /* void Horizont::init() */
//}}}


//{{{ void Horizont::setPosition(GLfloat x, GLfloat y, GLfloat z)
void Horizont::setPosition(float  x, float y, float z)
{
		pos.X = x; pos.Y = y; pos.Z = z;
} /* void Horizont::setPosition(GLfloat x, GLfloat y, GLfloat z) */
//}}}


//{{{ void Horizont::setPosition(vectord v)
void Horizont::setPosition(vectord &v)
{
		//pos = v;
} /* void Horizont::setPosition(vectord v) */
//}}}

		
//{{{ virtual Horizont::draw()
void Horizont::draw()
{
	if (!tex) return;		// do nothing if we have no texture.
	glPushMatrix();
	glTranslatef(pos.X, pos.Y, pos.Z);

	glBindTexture(GL_TEXTURE_2D, tex->getTexture());
	tex->setupTex();

	//glEnableClientState(GL_VERTEX_ARRAY);
	//glVertexPointer((segments) * 3 + 1, GL_FLOAT, 0, points);
	//glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	//glTexCoordPointer((segments) * 3 + 1, GL_FLOAT, 0, texPoints);
	//glDrawElements(GL_TRIANGLE_STRIP, (segments+1) * 2, GL_UNSIGNED_INT, idxStrip1);

	glPolygonMode(GL_BACK, GL_FILL);
	
	int idx;
	// Strip 1:
	glBegin(GL_TRIANGLE_STRIP);
	for(int i=0; i<(segments+1); ++i) {
		idx = i+segments+1;
		glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
		glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
		idx = i;
		glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
		glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	}
	idx = segments;
	glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
	glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	idx = 0;
	glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
	glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	glEnd();

	// Strip 2:
	glBegin(GL_TRIANGLE_STRIP);
	//glPolygonMode(GL_BACK, GL_LINE);
	for(int i=0; i<(segments+1); ++i) {
		idx = i+(segments+1)*2;
		glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
		glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
		idx = i+(segments+1);
		glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
		glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	}
	idx = segments*2;
	glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
	glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	idx = segments;
	glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
	glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	glEnd();

	// Fan:
	glBegin(GL_TRIANGLE_FAN);
	idx = (segments+1)*3;
	glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
	glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	for(int i=1; i<segments+2; ++i) {
		idx = ((segments+1)*2 - 1) + i;
		glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
		glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	}
	/*
	idx = segments*2;
	glTexCoord2f(texPoints[idx*2], texPoints[idx*2+1]);
	glVertex3f(points[idx*3], points[idx*3+1], points[idx*3+2]);
	*/

	glPolygonMode(GL_BACK, GL_LINE);
	glEnd();

	glPopMatrix();
} /* virtual Horizont::draw() */
//}}}


// vim:fdm=marker:fdc=2:ts=4
