///*
//	Process file
//	Class: CClothSimul - simulace tkaniny
//	Author: Michal Jirouš
//	Date 11.1.2008
//*/
//
//#include "clothsimul.h"
//#include "player.h"
//#include "mathematic.h"
//CClothSimul::CClothSimul(int iWidth, int iHeight, float fDistance, TextureElement *Texture, Vector axis, std::string sConstraint, Vector haxis)
//{
//	m_iWidth = iWidth;				//pocet bodu v ose x
//	m_iHeight = iHeight;			//pocet bodu v ose y
//	m_fPointDistance = fDistance;	//vzdalenost mezi body v ose
//	m_sClassName = "cloth_simul";	//jmeno tridy
//	m_Texture = Texture;			//prirazeni objektu textury
//	m_vecAxis = axis;				//smer osy X v prostoru
//	m_vecHAxis = haxis;				//smer osy Y v prostoru
//	m_sConstraints = sConstraint;	//retezec pevnych bodu -> format: x,y;m,n;	( prvni bod = 0 )
//	m_bReacting = true;				//udava zda bude latka reagovat na vnitrni sily pruzin a napr vitr
//	m_bCollide = true;				//udava pouziti kolizi
//}
//
///* Nastaveni parametru */
//void CClothSimul::setParameters( int value )	
//{
//	if( value & 1  )	m_bReacting = false;
//	if( value & 2 )		m_bCollide = false;
//}
//
///* funkce vytvari body, pruziny a trojuhelniky v zavislosti na parametrech */
//void CClothSimul::createClothModel()
//{
//	ClothPoint ***ClothPointField;	//vytvorime dvourozmerne pole bodu
//	ClothPointField = new ClothPoint**[m_iHeight];
//	for( int i = 0; i < m_iHeight; i++ )
//	{
//		ClothPointField[i] = new ClothPoint*[m_iWidth];
//		for( int j=0;j< m_iWidth; j++ )
//		{
//			ClothPointField[i][j] = new ClothPoint();
//			ClothPointField[i][j]->m_bMoveAble = true;
//		}
//
//	}
//
//	/* vypocitame vzdalenost mezi texturovacimi koordinaty */
//	float fXCoordDistance =  1.0f /  (float)(m_iWidth-1);
//	float fYCoordDistance =  1.0f / (float)(m_iHeight-1);
//
//	/* a vzdalenost mezi body v prostoru */
//	Vector vecXStep = Vector( m_vecAxis, m_fPointDistance );
//	Vector vecYStep = Vector( m_vecHAxis, m_fPointDistance );
//
//	/* Pak kazdy bod */
//	for( int y = 0; y < m_iHeight; y++ )
//	{
//		for( int x=0;x< m_iWidth; x++ )
//		{
//			/* ulozime do seznamu bodu */
//			m_listPoints.push_back( ClothPointField[y][x] );
//
//			/* Nastavine texturovaci souradnice */
//			ClothPointField[y][x]->x_coord = x * fXCoordDistance;
//			ClothPointField[y][x]->y_coord = 1.0f -y * fYCoordDistance;
//
//			/* a pozici bodu v prostoru */
//			ClothPointField[y][x]->core = getOrigin() + vecXStep * x + vecYStep * y;
//
//			/* Pote testujeme vyskyt sousedu a vytvarime vazby bodu se sousedy v poli */
//			if( x + 1 < m_iWidth && y + 1 < m_iHeight )	//lze vytvorit trojuhelnik a to 2 z kazdeho ctverce
//			{
//				ClothRelation *newRelation = new ClothRelation();	//zde krizem	\
//
//				newRelation->A = ClothPointField[y][x+1];
//				newRelation->B = ClothPointField[y+1][x];
//				
//				/* Nove vzniklou vazbu ( pruzinu ) vzdy vlozime do seznamu pruzin */
//				m_listRelations.push_back( newRelation );
//
//				/* a samozrejme i do seznamu obou bodu */
//				ClothPointField[y+1][x]->m_listRelations.push_back( newRelation );
//				ClothPointField[y][x+1]->m_listRelations.push_back( newRelation );
//
//				newRelation = new ClothRelation();	//zde krizem	/
//
//				newRelation->A = ClothPointField[y][x];
//				newRelation->B = ClothPointField[y+1][x+1];
//				m_listRelations.push_back( newRelation );
//
//				ClothPointField[y][x]->m_listRelations.push_back( newRelation );
//				ClothPointField[y+1][x+1]->m_listRelations.push_back( newRelation );
//				
//				/* A take vytvorime 2 trojuhelniky z kazdeho ctverce */
//				ClothTriangle newTriangle;
//				newTriangle.points[0] = ClothPointField[y][x];
//				newTriangle.points[1] = ClothPointField[y+1][x];
//				newTriangle.points[2] = ClothPointField[y+1][x+1];
//				m_listTriangles.push_back( newTriangle );
//				newTriangle.points[0] = ClothPointField[y][x];
//				newTriangle.points[1] = ClothPointField[y+1][x+1];
//				newTriangle.points[2] = ClothPointField[y][x+1];
//				m_listTriangles.push_back( newTriangle );
//			}
//
//			if( x + 1 < m_iWidth )	//zde doprava
//			{
//				ClothRelation *newRelation = new ClothRelation();
//
//				newRelation->A = ClothPointField[y][x];
//				newRelation->B = ClothPointField[y][x+1];
//				m_listRelations.push_back( newRelation );
//
//				ClothPointField[y][x]->m_listRelations.push_back( newRelation );
//				ClothPointField[y][x+1]->m_listRelations.push_back( newRelation );
//			}
//			if( y + 1 < m_iHeight )	//zde dolu
//			{
//				ClothRelation *newRelation = new ClothRelation();
//
//				newRelation->A = ClothPointField[y][x];
//				newRelation->B = ClothPointField[y+1][x];
//				m_listRelations.push_back( newRelation );
//
//				ClothPointField[y][x]->m_listRelations.push_back( newRelation );
//				ClothPointField[y+1][x]->m_listRelations.push_back( newRelation );
//			}
//		}
//	}
//
//	/* Nakonec projedeme retezec s informacemi o nepohyblivych bodech */
//	while( !m_sConstraints.empty() )
//	{
//		if( m_sConstraints == "none" ) break;
//		size_t index = m_sConstraints.find_first_of(',');
//		std::string firstValue = m_sConstraints.substr(0, index);
//		if(index+1 >= m_sConstraints.length())	break;
//		m_sConstraints=m_sConstraints.substr( index+1, m_sConstraints.length());
//
//		index = m_sConstraints.find_first_of(';');
//		std::string secondValue = m_sConstraints.substr(0, index);
//
//		int x_index = stringToInt( firstValue );
//		int y_index = stringToInt( secondValue );
//
//		/* a takovemu bodu nastavime nemoznost pohybu */
//		if( x_index >= 0 && x_index < m_iWidth && y_index >= 0 && y_index < m_iHeight)
//			ClothPointField[y_index][x_index]->m_bMoveAble = false;
//
//		if(index<m_sConstraints.length())
//			m_sConstraints=m_sConstraints.substr( index+1, m_sConstraints.length());
//		else
//			break;
//	}
//
//	m_sConstraints.clear();
//
//	for( int y = 0; y < m_iHeight; y++ )
//		delete [] ClothPointField[y];
//	delete [] ClothPointField;
//}
//
///* priprava objektu */
//void CClothSimul::compile()
//{
//	createClothModel();	//vytvoreni modelu latky
//
//	/* Vypocet zakladni vzdalenosti bodu pruziny */
//	for(std::list<ClothRelation*>:: iterator i = m_listRelations.begin(); i != m_listRelations.end(); ++i)
//	{
//		(*i)->baseDistance = ((*i)->A->core - (*i)->B->core).absolute();
//		(*i)->m_vecForce = Vector();
//	}
//}
//
///* priprava ke smazani objektu */
//void CClothSimul::decompile()
//{
//	/* Smazani vsech pruzin */
//	for(std::list<ClothRelation*>::iterator i = m_listRelations.begin(); i != m_listRelations.end(); i++)
//		delete (*i);
//
//	m_listRelations.clear();
//	m_listTriangles.clear();
//
//	/* a bodu latky */
//	for( std::list<ClothPoint*>::iterator i = m_listPoints.begin(); i != m_listPoints.end(); ++i )
//		delete (*i);
//	
//	m_listPoints.clear();
//}
//
///* Vykreslovaci funkce */
//void CClothSimul::draw()
//{
//	glPushAttrib(GL_ENABLE_BIT);
//	glDisable(GL_CULL_FACE);
//	glDisable(GL_LIGHTING);
//	glShadeModel(GL_FLAT);
//
//	if(m_Texture != NULL)
//		glBindTexture(GL_TEXTURE_2D, m_Texture->texture_id);
//	
//	/* Vykreslujeme ulozene trojuhelniky */
//	for(std::list<ClothTriangle>::iterator i = m_listTriangles.begin(); i != m_listTriangles.end(); i++)
//	{
//		glBegin( GL_TRIANGLES );
//		for(int j = 0; j < 3; j++)
//		{
//			glTexCoord2f((*i).points[j]->x_coord,(*i).points[j]->y_coord);
//			glVertex3f( (*i).points[j]->core[0], (*i).points[j]->core[1], (*i).points[j]->core[2] );
//		}
//		glEnd();
//	}
//	glPopAttrib();
//	glShadeModel(GL_SMOOTH);
//}
//
///* Pomocne struktury pro detekci kolizi, ktere nesou informaci o pohyblivych objektech a stenach objektu */
///*struct ThisBrushes
//{
//	polygonBrush *brush;
//	int id;
//	ThisBrushes( polygonBrush *p, int i)	: brush(p), id(i) {}
//};
//
//struct ThisMoves
//{
//	CBaseObject* object;
//	int id;
//	ThisMoves( CBaseObject* p, int i)	: object(p), id(i) {}
//};*/
//
///* periodicky spoustena funkce, kde se prepocitavaji sily a kolize */
//void CClothSimul::run()
//{
//	if( !m_bReacting ) return;	//pri zadne reakci objektu se nemusi nic pocitat
//
//	/* Vytvorime seznamy pohyblivych objektu a sten objektu */
//	//list<ThisMoves> moveAbleObjects;
//	//list<ThisBrushes> objectList;
//	
//	/* Pokud latka muze kolidovat */
//	/*if( m_bCollide )
//	{
//		m_pBoundingBox.setRange( 5.0f );	//rozsirime bounding box o 5 bodu do vsech smeru
//
//		SceneObject *tmp = getSceneObjectRoot();
//		int index = 0;
//		while( tmp != NULL )	//pro kazdy objekt sceny
//		{
//			++index;
//			if( tmp->object->isColliding() )	//otestujem, zda je objekt typem koliznim
//			{
//				polygonBrush *tmpBrush = tmp->object->getPolygonBrush();
//				while(tmpBrush != NULL)	//a pote pro vsechny jeho podobjekty (Brushe -> 1 konvexni 3D model ) 
//				{
//					//otestujeme moznost kolize pomoci bounding boxu
//					if( tmpBrush->m_pPointsinfo->compare( &m_pBoundingBox ) )	
//						objectList.push_back( ThisBrushes(tmpBrush, index) );	//v pripade moznosti kolize objekt ulozime
//
//					tmpBrush = tmpBrush->next;
//				}
//			}
//
//			//pokud se objekt muze pohzbovat ulozime ho do seznamu pohyblivych objektu
//			if( tmp->object->isMoveAble() )		
//				moveAbleObjects.push_back( ThisMoves(tmp->object, index) );
//
//			tmp = tmp->next;
//		}
//	}*/
//
//	/* Nasledne prepocitame sily vsech pruzin */
//	for(std::list<ClothRelation*>:: iterator i = m_listRelations.begin(); i != m_listRelations.end(); ++i)
//		(*i)->calculateForce();		
//
//	m_fGravity = gamevarsLibrary::getfData("sv_gravity") / 10000.0f;	//nastavime gravitaci
//	Vector gravity(0.0f,0.0f,-m_fGravity);
//	Vector fansForces;
//
//	//vypocitame vysledny vektor vetru
//	for(std::list<CFan*>::iterator i = m_fanList.begin(); i != m_fanList.end(); ++i)
//		fansForces += (*i)->getWindForceVector();
//
//	/* Resetujeme a nastavime zakladni hodnoty bounding boxu */
//	m_pBoundingBox.clear();
//	m_pBoundingBox.setBasicValues( (*m_listPoints.begin())->core );
//
//	/* Pak pro kazdy bod latky */
//	for( std::list<ClothPoint*>::iterator iterClothPoint = m_listPoints.begin(); iterClothPoint != m_listPoints.end(); ++iterClothPoint)
//	{
//		if((*iterClothPoint)->m_bMoveAble)	//otestujeme, zda se muze pohybovat
//		{
//			/* Pokud ano, tak secteme vsechny sily pruzin, ktere na nej pusobi*/
//			for(std::list<ClothRelation*>:: iterator i = (*iterClothPoint)->m_listRelations.begin(); i != (*iterClothPoint)->m_listRelations.end(); ++i)
//			{
//				if( (*iterClothPoint) == (*i)->A )	//obracene
//					(*iterClothPoint)->resultForce += (*i)->m_vecForce;
//				else
//					(*iterClothPoint)->resultForce -= (*i)->m_vecForce;
//			}
//			(*iterClothPoint)->resultForce += gravity;		//pak pricteme jeste gravitaci
//			(*iterClothPoint)->resultForce += fansForces;	//a vitr
//			(*iterClothPoint)->resultForce = (*iterClothPoint)->resultForce * 0.97f;	//koeficient odporu
//
//			/* Pokud latka muze kolidovat */
//			/*if( m_bCollide )
//			{	
//				// Vytvorime o neco delsi vektor pohybu bodu z vysledneho vektoru 
//				Vector tmpMove( (*iterClothPoint)->resultForce, (*iterClothPoint)->resultForce.absolute() + 1.0f );
//				
//				float fDistance = 1.0f;		//vzdalenost od kolizni roviny
//				Vector normalVector;		//normalovy vektor teto roviny
//				Point tmpMovedPoint;		//bod vzdaleny od bodu latky o vektor pohybu pohybliveho objektu
//				Point tmpPoint;				//bod vzdaleny od bodu latky o vektor pohybu bodu
//
//				// pro vsechny pohyblive objekty
//				for( list<ThisMoves>::iterator i = moveAbleObjects.begin(); i != moveAbleObjects.end(); ++i)
//				{
//					//zatim funguje jen s hracem, ktery je kvadr
//					if( (*i).object->getClassName() == "player" )
//					{
//						CPlayer *tmpPlayer = reinterpret_cast<CPlayer*>( (*i).object );
//
//						//nastavime vysledny bod = Bod latky - vektor pohybu hrace
//						tmpMovedPoint.x = (*iterClothPoint)->core[0] + tmpPlayer->m_vecMove[0];
//						tmpMovedPoint.y = (*iterClothPoint)->core[1] + tmpPlayer->m_vecMove[1];
//						tmpMovedPoint.z = (*iterClothPoint)->core[2];
//
//						//a otestujeme ho, zda lezi v hraci
//						if( tmpPlayer->m_pPointsinfo->isPointInCube( tmpMovedPoint.x, tmpMovedPoint.y, tmpMovedPoint.z ) )
//						{
//							tmpMovedPoint.x = (*iterClothPoint)->core[0] - tmpPlayer->m_vecMove[0];
//							tmpMovedPoint.y = (*iterClothPoint)->core[1] - tmpPlayer->m_vecMove[1];
//														
//							//pokud ano, tak v pripade pohybu objektu dojde ke kolizi
//							for( list<ThisBrushes>::iterator j = objectList.begin(); j != objectList.end(); j++ )
//							{	
//								//otestujeme, jestli dojde ke kolizi, kdyz se bod pohne o vektor pohybu objektu
//								if( isInObject( (*j).brush->firstPolygon , &tmpMovedPoint, normalVector, fDistance ) )
//								{
//									//nedetekujeme kolize s puvodcem pohybu
//									if( (*i).id == (*j).id )
//										continue;
//
//									(*iterClothPoint)->m_bIsColliding = true;
//								}
//							}
//
//							//pokud ke kolizi nedoslo, tak se bod muze posunout o vektor pohybu pohybujiciho se objektu
//							if( !(*iterClothPoint)->m_bIsColliding )
//							{
//								(*iterClothPoint)->core.field[0] -= tmpPlayer->m_vecMove[0];
//								(*iterClothPoint)->core.field[1] -= tmpPlayer->m_vecMove[1];
//							}
//						}
//					}
//				}
//
//				(*iterClothPoint)->m_bIsColliding = false;
//				
//				//dale testujeme zakladni staticke kolize
//
//				//bod se nastavi na souradnice pri posunu bodu o jeho pohybovy vektor
//				tmpPoint.x = (*iterClothPoint)->core[0] + tmpMove[0];	
//				tmpPoint.y = (*iterClothPoint)->core[1] + tmpMove[1];
//				tmpPoint.z = (*iterClothPoint)->core[2] + tmpMove[2];
//
//				//a testuje se, zda se neocitne v nejakem objektu
//				for( list<ThisBrushes>::iterator i = objectList.begin(); i != objectList.end(); i++ )
//				{
//					//dale se jeste pocita i nmejblizsi vzdalenost od roviny a jeji normalovy vektor
//					if( isInObject( (*i).brush->firstPolygon , &tmpPoint, normalVector, fDistance ) )
//						(*iterClothPoint)->m_bIsColliding = true;
//				}
//
//				//pak se kolize stejnym zpusobem prepocitaji jeste 2x
//				for( int k = 0; k < 2; k++)
//				{
//					if( fDistance < 0.5f && (*iterClothPoint)->m_bIsColliding)
//					{
//						(*iterClothPoint)->m_bIsColliding = false;
//						
//						//a to z duvodu tzv. "klouzani" po stenach objektu
//						
//						//vytvorime vektor, ktery lezi v kolizni rovine a zaroven udrzuje smer pohybu
//						Vector movement = normalVector * ((*iterClothPoint)->resultForce * normalVector);
//						Vector tmpMove = Vector( movement, movement.absolute() + 1.0f );
//
//						tmpPoint.x = (*iterClothPoint)->core[0] + tmpMove[0];
//						tmpPoint.y = (*iterClothPoint)->core[1] + tmpMove[1];
//						tmpPoint.z = (*iterClothPoint)->core[2] + tmpMove[2];
//						fDistance = 1.0f;
//						for( list<ThisBrushes>::iterator i = objectList.begin(); i != objectList.end(); i++ )
//						{
//							if( isInObject( (*i).brush->firstPolygon , &tmpPoint,normalVector, fDistance ) )
//							{
//								(*iterClothPoint)->resultForce = Vector();
//								(*iterClothPoint)->m_bIsColliding = true;
//								if( k == 1 )
//									break;
//							}
//						}
//						
//						//v pripade ze nedojde ke kolizi muzeme nastavit novy vektor pohybu
//						if( !(*iterClothPoint)->m_bIsColliding )
//							(*iterClothPoint)->resultForce = movement;
//					}
//				}
//			}*/
//		}
//
//		/* Nakonec pokud neni bod kolizni, tak nastavime novou pozici bodu */
//		if( !(*iterClothPoint)->m_bIsColliding )
//			(*iterClothPoint)->core += (*iterClothPoint)->resultForce;
//
//		(*iterClothPoint)->m_bIsColliding = false;		//resetujeme vlastnost
//		
//		/* Pokud latka muze kolidovat, tak pocitame hodnoty bounding boxu */
//		if( m_bCollide )
//			m_pBoundingBox.updateData( (*iterClothPoint)->core );
//	}
//}
