#include "kugel.h"
#include "Spring.h"

#define PI 3.1415926535897932384626433832795


kugel::kugel(void)
{
	
	
}

bool kugel::init()
{

	
   if(!STexture.LoadTGA("pics/env2.tga")) return false; 
   glGenTextures(1, &STexture.ID);
   
   glBindTexture(GL_TEXTURE_2D, STexture.ID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

   int type = STexture.type == 3 ? GL_RGB : GL_RGBA;
   gluBuild2DMipmaps(GL_TEXTURE_2D, STexture.type, STexture.imageWidth, STexture.imageHeight,
                     type, GL_UNSIGNED_BYTE, STexture.image);
   

	pos = Vector3(0.0,5.0,0.0);
	speed = Vector3(0.0,0.0,0.0);
	acceleration = Vector3(0.0,0.0,0.0);
	gravity = Vector3(0.0,-0.1,0.0);

	//use same value for both (discs & sclices)... or find the bug
	discs = 12;
	slices = 12;
	radius = 1.0;
	
	delta_t = 0.015;
	//delta_t = 0.1;
	damp = 0.5;
	mid_stiffness = 20.0; //stiffness for midpoint springs
	sp_stiffness = 10.0;

	is_changeing = false;
	vertices_touching_ground = 0;

	DRAW_VERTICES = false;
	DRAW_SPRINGS = false;
	DRAW_TRIANGLES = true;

	vertices.clear();

	
	create_vertices();
	create_springs(sp_stiffness);

	return true;
}


void kugel::create_springs(double stiffness){
	int i,j;

	Vector3 *v0,*v1,*v2,*v3,*v4,*v5,*v6,*v7,*v8,*v9;
	double l;  //debug length
	Spring *s;
	for(i=0;i<discs;i++){

		//handle endpoints explicitly
			if (i==0) {
				//the first endpoint of sphere (only once!)
				v0 = &vertices[0]->coords;
				std::vector<Vector3*> arr;
				for (int k=0; k<slices; k++)
					{						
						arr.push_back(&vertices[1+  (k%slices)]->coords);
						s = new Spring(v0,arr[k],(*v0-*arr[k]).length(),stiffness);
						vertices[0]->springs.push_back(s);

					}
				arr.clear();

					//midpoint
				v9 = &vertices[2+(discs-2)*slices]->coords;
					l = (*v0-*v9).length();
				//	printf ("length9: %f\n",l);
				s = new Spring(v0,v9,(*v0-*v9).length(),mid_stiffness);
				vertices[0]->springs.push_back(s);

			} else if (i == (discs-1)){
				//the second endpoint
				v0 = &vertices[1+ (discs-2)*slices]->coords;
				std::vector<Vector3*> arr;
				for (int k=0; k<slices; k++)
					{
						arr.push_back ( &vertices[1+(discs-3)*slices+  (k%slices)]->coords);
						s = new Spring(v0,arr[k],(*v0-*arr[k]).length(),stiffness);
						vertices[1+ (discs-2)*slices]->springs.push_back(s);

					}
				arr.clear();
					//midpoint
				v9 = &vertices[2+(discs-2)*slices]->coords;
					l = (*v0-*v9).length();
				//	printf ("length9: %f\n",l);
				s = new Spring(v0,v9,(*v0-*v9).length(),mid_stiffness);
				vertices[1+ (discs-2)*slices]->springs.push_back(s);
			}

			else //if (i >0 && i < (discs-1))
			{ //normal cases


				for(j=0;j<slices;j++){

					
					//printf("disc: %i, slice: %i\n",i,j);

						int current_index = 1+ ((i-1)*discs)+ (j %slices);
						v0 = &vertices[current_index]->coords;

							//midpoint
							v9 = &vertices[2+(discs-2)*slices]->coords;
								l = (*v0-*v9).length();
							//	printf ("length9: %f\n",l);
							s = new Spring(v0,v9,(*v0-*v9).length(),mid_stiffness);
							vertices[current_index]->springs.push_back(s);
						if (i==1) { //this is the first disc
									//get vertices on upper disc  
								v1 = &vertices[1+(i)*discs+((j)%slices)]->coords;
									l = (*v0-*v1).length();
								//	printf ("length1: %f\n",l);
								s = new Spring(v0,v1,(*v0-*v1).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v2 = &vertices[1+(i)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v2).length();
								//	printf ("length2: %f\n",l);
								s = new Spring(v0,v2,(*v0-*v2).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v8 = &vertices[1+(i)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v8).length();
								//	printf ("length8: %f\n",l);
								s = new Spring(v0,v8,(*v0-*v8).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								// the two neighbour vertices on same disc
								
								v3 = &vertices[1+(i-1)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v3).length();
								//	printf ("length3: %f\n",l);
								s = new Spring(v0,v3,(*v0-*v3).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v7 = &vertices[1+(i-1)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v7).length();
								//	printf ("length7: %f\n",l);
								s = new Spring(v0,v7,(*v0-*v7).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								//and the 1st one
								v5 = &vertices[0]->coords;
									l = (*v0-*v5).length();
								//	printf ("length5: %f\n",l);
								s = new Spring(v0,v5,(*v0-*v5).length(),stiffness);
								vertices[current_index]->springs.push_back(s);


						} //end first disc

						else if (i == discs-2)  //handle disc to 2nd endpoint
						{
								//the lower vertices
								v4 = &vertices[1+(i-2)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v4).length();
								//	printf ("length4: %f\n",l);
								s = new Spring(v0,v4,(*v0-*v4).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v5 = &vertices[1+(i-2)*discs+((j)%slices)]->coords;
									l = (*v0-*v5).length();
								//	printf ("length5: %f\n",l);
								s = new Spring(v0,v5,(*v0-*v5).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v6 = &vertices[1+(i-2)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v6).length();
								//	printf ("length6: %f\n",l);
								s = new Spring(v0,v6,(*v0-*v6).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								// the two neighbour vertices on same disc
								
								v3 = &vertices[1+(i-1)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v3).length();
								//	printf ("length3: %f\n",l);
								s = new Spring(v0,v3,(*v0-*v3).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v7 = &vertices[1+(i-1)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v7).length();
								//	printf ("length7: %f\n",l);
								s = new Spring(v0,v7,(*v0-*v7).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								//and the last one
								v1 = &vertices[1+ (discs-2)*slices]->coords;
									l = (*v0-*v1).length();
								//	printf ("length1: %f\n",l);
								s = new Spring(v0,v1,(*v0-*v1).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

						} // end else if 2nd endpoint

						else {
								//get vertices on upper disc  
								v1 = &vertices[1+(i)*discs+((j)%slices)]->coords;
									l = (*v0-*v1).length();
								//	printf ("length1: %f\n",l);
								s = new Spring(v0,v1,(*v0-*v1).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v2 = &vertices[1+(i)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v2).length();
								//	printf ("length2: %f\n",l);
								s = new Spring(v0,v2,(*v0-*v2).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v8 = &vertices[1+(i)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v8).length();
								//	printf ("length8: %f\n",l);
								s = new Spring(v0,v8,(*v0-*v8).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								// the two neighbour vertices on same disc
								
								v3 = &vertices[1+(i-1)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v3).length();
								//	printf ("length3: %f\n",l);
								s = new Spring(v0,v3,(*v0-*v3).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v7 = &vertices[1+(i-1)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v7).length();
								//	printf ("length7: %f\n",l);
								s = new Spring(v0,v7,(*v0-*v7).length(),stiffness);
								vertices[current_index]->springs.push_back(s);


								//the lower vertices
								v4 = &vertices[1+(i-2)*discs+((j+1)%slices)]->coords;
									l = (*v0-*v4).length();
								//	printf ("length4: %f\n",l);
								s = new Spring(v0,v4,(*v0-*v4).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v5 = &vertices[1+(i-2)*discs+((j)%slices)]->coords;
									l = (*v0-*v5).length();
								//	printf ("length5: %f\n",l);
								s = new Spring(v0,v5,(*v0-*v5).length(),stiffness);
								vertices[current_index]->springs.push_back(s);

								v6 = &vertices[1+(i-2)*discs+((slices+j-1)%slices)]->coords;
									l = (*v0-*v6).length();
								//	printf ("length6: %f\n",l);
								s = new Spring(v0,v6,(*v0-*v6).length(),stiffness);
								vertices[current_index]->springs.push_back(s);


						}
				} //end j

			}// end else normal case


		

	}//end i

}



void kugel::create_vertices(){
	double dphi = (PI)/(discs);
	double drho = (2.0*PI)/(slices);
	double x,y,z;
	int i = 0,p,r;

	//vertices.push_back(new kugel_vertex(Vector3(0,0,cos(0.0))));
	//(remark: the sphere gets build from +z to -z) and cw on xy plane.
	//anyway the coord. system is here the normal x,y,z system and not comp. graphics: x,-z,y

	//create only 1 vertice for the endings
	x = 0.0;
	y = 0.0;
	z = radius;
	vertices.push_back(new kugel_vertex(Vector3(x,y,z)+ pos));


	for(p = 1; p < discs-1; p++){
		for(r = 0; r < slices; r++){
			double new_p = (double)p + (double)p/(double)discs;
			x = radius * sin(new_p*dphi) * cos(r*drho);
			y = radius * sin(new_p*dphi) * sin(r*drho);
			z = radius * cos(new_p*dphi);
			vertices.push_back(new kugel_vertex(Vector3(x,y,z)+ pos));
		}
	}

	//second closing
	x = 0.0;
	y = 0.0;
	z = -radius;
	vertices.push_back(new kugel_vertex(Vector3(x,y,z)+ pos));

	//push midpoint
	vertices.push_back(new kugel_vertex(Vector3(0,0,0)+ pos));
}

void kugel::update_internal_forces(){
	std::vector<Spring*>::iterator s;
	std::vector<kugel_vertex*>::iterator v;
	
	double delta_col = 50.0;	//a good value for the penalty based method?  needs to be enough big to compete spring forces
	double mass = 1.0;	//some correction value

	vertices_touching_ground = 0;


	for(v = vertices.begin(); v != vertices.end(); ++v){
		Vector3 f = Vector3(0,0,0);
		for(s=(*v)->springs.begin(); s!=(*v)->springs.end();++s){
			f += (*s)->Force1();
		}
		
		Vector3 current = (*v)->coords;

		Vector3 normal;

		//separate handle midpoint (other damp) and the normal points


		//handle midpoint
		if ((*v) == vertices[2+(discs-2)*slices]) {
			//synchronise now with midpoint/position
			pos = current;
			//earlier colision for midpoint
			if (bforce_midpoint_collision(current,normal))
			{ 
				f+= normal*delta_col;
				//punkte auf dem boden bewegen sich nicht
				//(*v)->velocity.x = 0;
				//(*v)->velocity.z = 0;
			}

			double mid_point_damp = 0.3;
			double mid_point_mass = 2.0;
			f += acceleration;
			f += gravity;
			f -= (*v)->velocity*(mid_point_damp);

			//leapfrog integration

			// integrate velocities
			(*v)->velocity +=  f *(delta_t/mid_point_mass);

			// integrate positions
			(*v)->coords +=(*v)->velocity*delta_t;




		}
		else	//handle normal points
		{

			if (bforce_collision(current,normal)) {
				f+= normal*delta_col;
				//punkte auf dem boden bewegen sich nicht
				(*v)->velocity.x = 0;
				(*v)->velocity.z = 0;
				//if((*v)->touches_ground == false){vertices_touching_ground++;}
				//(*v)->touches_ground = true;
				vertices_touching_ground++;

			}else{
				//if((*v)->touches_ground == true){vertices_touching_ground--;}
				//(*v)->touches_ground = false;
			}


			f += acceleration;
			f += gravity;
			f -= (*v)->velocity*(damp);

			//leapfrog integration

			// integrate velocities
			(*v)->velocity +=  f *(delta_t/mass);

			// integrate positions
			(*v)->coords +=(*v)->velocity*delta_t;



		}//end else normal points
		
	}//end for vertices
}



void kugel::move(Vector3 delta)
{

}

void kugel::update_gravity (double dg)
{	
	acceleration = Vector3 (0,0,0);
	acceleration += Vector3 (0,dg*3.0,0);


}

void kugel::update(Vector3 dv)
{
	acceleration += dv *0.03;
	acceleration = acceleration*0.5;
	if (acceleration.length() <= 0.005)
		acceleration = Vector3(0.0,0.0,0.0);



}
void kugel::update(float dx,float dz)
{
	//float damp = 0.009;
	//speed = Vector3(speed.x+damp*dx, speed.y, speed.z+damp*dz);
	//pos = pos + speed;

}

void kugel::render()
{

	//glPushAttrib(GL_TEXTURE_BIT);
	//update_internal_forces();

	//glBlendFunc(GL_SRC_ALPHA,GL_ONE);

	//glEnable(GL_TEXTURE_2D);

	
	
	//glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
	//glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
	
	//glEnable(GL_TEXTURE_GEN_S);	
	//glEnable(GL_TEXTURE_GEN_T);	

	//glBindTexture(GL_TEXTURE_2D, STexture.ID);

	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glBlendFunc (GL_SRC_ALPHA, GL_SRC_COLOR);
	glTranslatef(-speed.z,speed.y,speed.x);
	GLfloat mat_color[4] = { 0.4, 0.4, 0.4, 1.0 };
	GLfloat mat_specular[4] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_shininess[] = { 40.0 };
	GLfloat mat_emessive[4] = { 0.2, 0.2, 0.2, .8 };

	glMaterialfv(GL_FRONT, GL_AMBIENT, mat_color);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_color);
	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
	//glMaterialfv(GL_FRONT, GL_EMISSION, mat_emessive);
	//glColor3f(1,0,0);

	//glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_BLEND);
	
	Vector3 *v,*v2,*v3, *v4;
	int c;
	Vector3 n, n2, n3, n4;
	Vector3 t1,t2,t3,t4;
	std::vector<Spring*>::iterator s;

	if (!is_changeing)
	{
	for(int i=0;i<discs;i++){
		if (i == 0 || i == discs -1)
			{
				if (!i)		//1st endpoint
				{
					c = 0; 
					v = &vertices[c]->coords;
					if(DRAW_SPRINGS){
						for(s=vertices[c]->springs.begin(); s!=vertices[c]->springs.end();++s){
							glBegin(GL_LINES);
							glVertex3f((*s)->p1->x,(*s)->p1->y,(*s)->p1->z);
							glVertex3f((*s)->p2->x,(*s)->p2->y,(*s)->p2->z);
							glEnd();
						}
					}
					if(DRAW_VERTICES){
						glPushMatrix();
						glTranslatef(v->x, v->y, v->z);
						glutSolidSphere(0.05, 5,5);
						glPopMatrix();
					}
					if(DRAW_TRIANGLES){
					
						glBegin(GL_TRIANGLES);
						n = Vector3(v->x,v->y,v->z).normalize();
						t1 = Vector3(asinf(n.x)/PI + 0.5,asinf(n.x)/PI + 0.5,0.0);

						std::vector<Vector3> normals;
						std::vector<Vector3*> t_vertices;
						std::vector<Vector3> tex_coords;
						for (int j=0; j<slices; j++)
						{
									
							
							c = 1+j;
							t_vertices.push_back( &vertices[c]->coords);
							Vector3 normal = Vector3(t_vertices[j]->x,t_vertices[j]->y,t_vertices[j]->z).normalize();	
							normals.push_back(normal);
							tex_coords.push_back(Vector3(asinf(normal.x)/PI + 0.5,asinf(n.y)/PI + 0.5,0.0));
						}
						for (int j=0; j<slices; j++)
						{
							glNormal3f(n.x, n.y, n.z);
							glTexCoord2f(t1.x,t1.y);
							glVertex3f(v->x, v->y, v->z);
							glNormal3f(normals[j].x, normals[j].y, normals[j].z);
							glTexCoord2f(tex_coords[j].x,tex_coords[j].y);
							glVertex3f(t_vertices[j]->x, t_vertices[j]->y, t_vertices[j]->z);
							glTexCoord2f(tex_coords[(j+1)%slices].x,tex_coords[(j+1)%slices].y);
							glNormal3f(normals[(j+1)%slices].x, normals[(j+1)%slices].y, normals[(j+1)%slices].z);
							glVertex3f(t_vertices[(j+1)%slices]->x, t_vertices[(j+1)%slices]->y, t_vertices[(j+1)%slices]->z);
							
						}
						glEnd();
						normals.clear();
						t_vertices.clear();
					
					}


				}else {	//2nd endpoint
					c = 1+(discs-2)*slices; 
					v = &vertices[c]->coords;
					if(DRAW_SPRINGS){
						for(s=vertices[c]->springs.begin(); s!=vertices[c]->springs.end();++s){
							glBegin(GL_LINES);
							glVertex3f((*s)->p1->x,(*s)->p1->y,(*s)->p1->z);
							glVertex3f((*s)->p2->x,(*s)->p2->y,(*s)->p2->z);
							glEnd();
						}
					}
					if(DRAW_VERTICES){
						glPushMatrix();
						glTranslatef(v->x, v->y, v->z);
						glutSolidSphere(0.05, 5,5);
						glPopMatrix();
					}
					if(DRAW_TRIANGLES){
					
						glBegin(GL_TRIANGLES);
						n = Vector3(v->x,v->y,v->z).normalize();
						t1 = Vector3(asinf(n.x)/PI + 0.5,asinf(n.x)/PI + 0.5,0.0);

						std::vector<Vector3> normals;
						std::vector<Vector3*> t_vertices;
						std::vector<Vector3> tex_coords;
						for (int j=0; j<slices; j++)
						{
							c = 1+(discs-3)*slices + j;				
							
							t_vertices.push_back( &vertices[c]->coords);

							Vector3 normal = Vector3(t_vertices[j]->x,t_vertices[j]->y,t_vertices[j]->z).normalize();	
							normals.push_back(normal);
							tex_coords.push_back(Vector3(asinf(normal.x)/PI + 0.5,asinf(n.y)/PI + 0.5,0.0));
							
						}
						for (int j=0; j<slices; j++)
						{
							glNormal3f(n.x, n.y, n.z);
							glTexCoord2f(t1.x,t1.y);
							glVertex3f(v->x, v->y, v->z);
							glNormal3f(normals[j].x, normals[j].y, normals[j].z);
							glTexCoord2f(tex_coords[j].x,tex_coords[j].y);
							glVertex3f(t_vertices[j]->x, t_vertices[j]->y, t_vertices[j]->z);
							glNormal3f(normals[(j+1)%slices].x, normals[(j+1)%slices].y, normals[(j+1)%slices].z);
							glTexCoord2f(tex_coords[(j+1)%slices].x,tex_coords[(j+1)%slices].y);
							glVertex3f(t_vertices[(j+1)%slices]->x, t_vertices[(j+1)%slices]->y, t_vertices[(j+1)%slices]->z);
							
						}
						glEnd();
						normals.clear();
						t_vertices.clear();
					
					}
				}

			}
		else {

		for(int j=0;j<slices;j++){
			
			c = 1 + (i-1)*(discs)+j;
			v = &vertices[c]->coords;
			if(DRAW_SPRINGS){
				for(s=vertices[c]->springs.begin(); s!=vertices[c]->springs.end();++s){
					glBegin(GL_LINES);
					glVertex3f((*s)->p1->x,(*s)->p1->y,(*s)->p1->z);
					glVertex3f((*s)->p2->x,(*s)->p2->y,(*s)->p2->z);
					glEnd();
				}
			}

			if(DRAW_VERTICES){
				glPushMatrix();
				glTranslatef(v->x, v->y, v->z);
				glutSolidSphere(0.05, 5,5);
				glPopMatrix();
			}
			
			if(DRAW_TRIANGLES){
				if (i<discs-2)
				{
				glBegin(GL_TRIANGLES);
				n = Vector3(v->x,v->y,v->z).normalize();
				t1 = Vector3(asinf(n.x)/PI + 0.5,asinf(n.x)/PI + 0.5,0.0);
				c = 1+(i)*discs+j;
				v2 = &vertices[c]->coords;
				n2 = Vector3(v2->x,v2->y,v2->z).normalize();
				t2 = Vector3(asinf(n2.x)/PI + 0.5,asinf(n2.x)/PI + 0.5,0.0);
				c = 1+(i-1)*discs+((j+1)%slices);
				v3 = &vertices[c]->coords ;
				n3 = Vector3(v3->x,v3->y,v3->z).normalize();
				t3 = Vector3(asinf(n3.x)/PI + 0.5,asinf(n3.x)/PI + 0.5,0.0);
				c = 1+(i)*discs+((slices+j-1)%slices);
				v4 = &vertices[c]->coords;
				n4 = Vector3(v4->x,v4->y,v4->z).normalize();
				t4 = Vector3(asinf(n4.x)/PI + 0.5,asinf(n4.x)/PI + 0.5,0.0);
			
				glNormal3f(n2.x, n2.y, n2.z);
				glTexCoord2f(t2.x,t2.y);
				glVertex3f(v2->x, v2->y, v2->z);
				glNormal3f(n3.x, n3.y, n3.z);
				glTexCoord2f(t3.x,t3.y);
				glVertex3f(v3->x, v3->y, v3->z);
				glNormal3f(n.x, n.y, n.z);
				glTexCoord2f(t1.x,t1.y);
				glVertex3f(v->x, v->y, v->z);
				glNormal3f(n2.x, n2.y, n2.z);
				glTexCoord2f(t2.x,t2.y);
				glVertex3f(v2->x, v2->y, v2->z);
				glNormal3f(n4.x, n4.y, n4.z);
				glTexCoord2f(t4.x,t4.y);
				glVertex3f(v4->x, v4->y, v4->z);
				glNormal3f(n.x, n.y, n.z);
				glTexCoord2f(t1.x,t1.y);
				glVertex3f(v->x, v->y, v->z);
				glEnd();
				}
			}
		} //end for j
		}// end else
	} //end for i

	} //end if changeing
	else
	{
		render_delay++;
		
		Vector3 *v;
		for (int i=0; i<current_vertex; i++)
		{
			v = &vertices[i]->coords;
			glPushMatrix();
			glTranslatef(v->x, v->y, v->z);
			glutSolidSphere(0.05, 5,5);
			glPopMatrix();
		}
		if (render_delay > 5)
		{
			if (current_vertex == vertices.size())
				is_changeing = false;
			else current_vertex++;

		render_delay = 0;
		}


	}
	//glutSolidSphere(2.0,20,20);


	//glDisable(GL_TEXTURE_GEN_S);
	//glDisable(GL_TEXTURE_GEN_T);

	//glDisable(GL_TEXTURE_2D);

	glBlendFunc(GL_SRC_ALPHA,GL_ONE);	
	
	//glPopAttrib();

}


void kugel::toggle_vertices (void)
{
	if (DRAW_VERTICES) DRAW_VERTICES = false; else DRAW_VERTICES = true;
}
void kugel::toggle_springs (void)
{
	if (DRAW_SPRINGS)  DRAW_SPRINGS= false; else DRAW_SPRINGS = true;
}
void kugel::toggle_triangle (void)
{
	if (DRAW_TRIANGLES) DRAW_TRIANGLES = false; else DRAW_TRIANGLES = true;
}


bool kugel::bforce_collision (Vector3 p, Vector3 &n)
{
	//tests a point against the terrain (hardcoded; sorry)
	//returns the normal bei reference and returns true if it does collide

	//the main plane
	double border_z11 = -30.0;
	double border_z12 = 30.0;
	double border_x11 = -30.0;
	double border_x12 = 30.0;
	double plane_y1 = 0.0;

	//higher ground
	double border_z21 = -2.0;
	double border_z22 = 2.0;
	double border_x21 = -2.0;
	double border_x22 = 2.0;
	double plane_y2 = 2.0;

	//ramp
	Vector3 r1 = Vector3 (-10.0,0.0,-10.0);
	Vector3 r2 = Vector3 (5.0,5.0,-10.0);
	Vector3 r3 = Vector3 (5.0,5.0,-18.0);
	Vector3 r4 = Vector3 (-10.0,0.0,-18.0);

	bool plane_collision = false;  Vector3 plane_vector;
	bool ramp_collision = false;  Vector3 ramp_vector;


	double tol = 0.4;  //intersection tolerance

	if (border_z11 < p.z && p.z < border_z12 && border_x12 > p.x && p.x > border_x11) 
	{ //is on main plane
		if (p.y <= plane_y1) {n = plane_vector = Vector3 (0.0,-p.y,0.0); plane_collision = true; }

		//higher ground
		if (border_z21 < p.z && p.z < border_z22 && border_x22 > p.x && p.x > border_x21) 
		{//is on higher ground
			//simplification: if the point is near the top->lift it on top
			if (p.y >= plane_y2-tol && p.y <= plane_y2) {n = Vector3 (0.0,(plane_y2-p.y),0.0); return true; }
							//this offset should be set properly
			else {

				//compute reflection angle
				//TODO:
				//something with cos & dot product in 2d
				//refl = invec - 2 * (invec dot normal) * normal 
				//make the plane visible (render in plane) properly

			}

		} //end higher ground

		//ramp
		if (r1.z > p.z && p.z > r4.z && r1.x < p.x && p.x < r2.x)
		{
			//ramp it self
			Vector3 grad = Vector3 (r2.x-r1.x,r2.y-r1.y,0.0);
			Vector3 normal = Vector3 (grad.y,-grad.x,grad.z).normalize();		//it's (1,3)  2D
			double temp_y = (p.x-r1.x)/3.0;
			if (p.y <= temp_y && p.y >= temp_y-tol)  
			{
				temp_y = temp_y-p.y;
				Vector3 test = Vector3 (-0.0005,temp_y,0.0);
				n = ramp_vector = test;
				//refl = invec - 2 * (invec dot normal) * normal 
				//n = normal * temp_y;
				
				//return true;
				ramp_collision = true;


			}

			//ramp covering
			//refl = invec - 2 * (invec dot normal) * normal 

			//back
			else if (p.x<r2.x && p.x > r2.x-tol && p.y <r2.y-tol)
			{
				double temp_x = r2.x-p.x;
				n= ramp_vector = Vector3(temp_x,0.0,0.0);
				//return true;
				ramp_collision = true;
			}

			//nearer triangle
			else if (r1.z > p.z && p.z > r1.z - tol  && p.y <= temp_y)
			{
				double temp_z = r1.z-p.z;
				n= ramp_vector = Vector3(0.0,0.0,temp_z);
				//return true;
				ramp_collision = true;
			}
			//farer triangle
			else if (r3.z < p.z && p.z < r3.z + tol  && p.y <= temp_y)
			{
				double temp_z = p.z-r3.z;
				n= ramp_vector = Vector3(0.0,0.0,-temp_z);
				//return true;
				ramp_collision = true;
			}

			
		}//end ramp


		if (ramp_collision && plane_collision)
		{
			n = ramp_vector + plane_vector;
			return true;
		}
		else if (plane_collision) return true;
		else if (ramp_collision) return true;

			


	}//end on ground

	//and if the sphere is falling down...

	return false;

}


bool kugel::bforce_midpoint_collision (Vector3 p, Vector3 &n)
{
	//tests a point against the terrain (hardcoded; sorry)
	//returns the normal bei reference and returns true if it does collide
	//changed y value basically corrects the p.y to the base

	//the main plane
	double border_z11 = -30.0;
	double border_z12 = 30.0;
	double border_x11 = -30.0;
	double border_x12 = 30.0;
	double plane_y1 = 0.3;		//changed y value

	//higher ground
	double border_z21 = -2.0;
	double border_z22 = 2.0;
	double border_x21 = -2.0;
	double border_x22 = 2.0;
	double plane_y2 = 2.3;		//chandged y value

	//ramp
	//changed plane value (lift it higher, by changeing the x and y values)
	//and make it wider (change z value)	//then we can perform the same calculation as in normal case
	double plane_correction = 0.5;
	double plane_correction2 = 0.9;
	double plane_correction3 = 0.7;
	double point_correction = radius-0.15;
	Vector3 r1 = Vector3 (-10.0-plane_correction2,0.0,-10.0+point_correction);   
	Vector3 r2 = Vector3 (5.0+plane_correction3,5.0+plane_correction,-10.0+point_correction);
	Vector3 r3 = Vector3 (5.0+plane_correction3,5.0+plane_correction,-18.0-point_correction);
	Vector3 r4 = Vector3 (-10.0-plane_correction2,0.0,-18.0-point_correction);


	bool plane_collision = false;  Vector3 plane_vector;
	bool ramp_collision = false;  Vector3 ramp_vector;

	double tol = 0.4;  //intersection tolerance

	if (border_z11 < p.z && p.z < border_z12 && border_x12 > p.x && p.x > border_x11) 
	{ //is on main plane
		if (p.y <= plane_y1) {n = plane_vector = Vector3 (0.0,(plane_y1-p.y),0.0); plane_collision = true; }

		//higher ground
		if (border_z21 < p.z && p.z < border_z22 && border_x22 > p.x && p.x > border_x21) 
		{//is on higher ground
			//simplification: if the point is near the top->lift it on top
			if (p.y >= plane_y2-tol && p.y <= plane_y2) {n = Vector3 (0.0,(plane_y2-p.y),0.0); return true; }
							//this offset should be set properly
			else {

				//compute reflection angle
				//TODO:
				//something with cos & dot product in 2d
				//refl = invec - 2 * (invec dot normal) * normal 
				//make the plane visible (render in plane) properly

			}

		} //end higher ground

		//ramp
		
		if (r1.z > p.z && p.z > r4.z && r1.x < p.x && p.x < r2.x)
		{
			//ramp it self
			Vector3 grad = Vector3 (r2.x-r1.x,r2.y-r1.y,0.0);
			Vector3 normal = Vector3 (grad.y,-grad.x,grad.z).normalize();		//it's (1,3)  2D
			double temp_y = (p.x-r1.x)/3.0 +0.3;
			if (p.y <= temp_y && p.y >= temp_y-tol)  
			{
				temp_y = temp_y-p.y;
				Vector3 test = Vector3 (-0.0005,temp_y,0.0);
				n = ramp_vector = test;
				//refl = invec - 2 * (invec dot normal) * normal 
				//n = normal * temp_y;
				
				//return true;
				ramp_collision = true;


			}

			//ramp covering
			//refl = invec - 2 * (invec dot normal) * normal

			//back															//p.y+correction
			else if (p.x<r2.x && p.x > r2.x-0.9 && p.y < r2.y-tol)
			{
				double temp_x = r2.x-p.x;
				n= ramp_vector= Vector3(temp_x,0.0,0.0);
				//return true;
				ramp_collision =true;
			}

			//nearer triangle
			else if (r1.z > p.z && p.z > r1.z - tol  && p.y <= temp_y)
			{
				double temp_z = r1.z-p.z;
				n= ramp_vector = Vector3(0.0,0.0,temp_z);
				//return true;
				ramp_collision = true;
			}
			//farer triangle
			else if (r3.z < p.z && p.z < r3.z + tol  && p.y <= temp_y)
			{
				double temp_z = p.z-r3.z;
				n= ramp_vector = Vector3(0.0,0.0,-temp_z);
				//return true;
				ramp_collision = true;
			}


		}// end ramp


		if (ramp_collision && plane_collision)
		{
			n = ramp_vector + plane_vector;
			return true;
		}
		else if (plane_collision) return true;
		else if (ramp_collision) return true;

			


	}//end on ground

	//and if the sphere is falling down...

	return false;

}


void kugel::reconstitute (void)
{

	

	//DRAW_VERTICES = false;
	//DRAW_SPRINGS = false;
	//DRAW_TRIANGLES = true;

	vertices.clear();

	pos = pos + Vector3(0.0,0.5,0.0);
	
	create_vertices();
	create_springs(sp_stiffness);

	is_changeing = true;

	current_vertex = 0;
	render_delay = 0;


}

void kugel::reset (void)
{
	pos = Vector3(0.0,5.0,0.0);
	reconstitute();

}

void kugel::destroy (void)
{


}


kugel::~kugel(void)
{
}
