/*
 * ExNihilo 3D Engine
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Please read AUTHORS file !!!
 * 
 * $Id: ExCModel3DS.cpp,v 1.11 2002/11/24 11:59:01 data Exp $
 *
 */

#include "ExCModel3DS.h"

ExCModel3DS::ExCModel3DS(void)
{
Guard(ExCModel3DS::ExCModel3DS(void))
	ExCModel::ExCModel();
	SetName("ExCModel3DS");
	SetType(typeid(this).name());
	m_ListId=-1;
	m_CollisionGizmo=new ExCGizmoRectangle;
	m_CollisionCounter=0;
	HasList=false;
	HasArray=false;
	m_AlwaysDraw=false;
	SetVisibleState(true);
	//m_RenderMode=RENDER_DISPLAY_LIST;
	m_RenderMode=RENDER_VERTEX_ARRAY;
UnGuard
}

ExCModel3DS::~ExCModel3DS(void)
{
Guard(ExCModel3DS::~ExCModel3DS(void))
UnGuard
}
void ExCModel3DS::BuildArray(int Rendu)
{
Guard(void ExCModel3DS::BuildArray(int Rendu))
	ExCVec3D VecAB,VecBC,VecCA,VecFace;
	ExCVec3D VecX,VecY,VecZ;
	ExCVec2D VecTAB,VecTBC,VecTCA;
			
	for(unsigned int i=0;i<m_VecObject->size();i++)//draw all objects
	{
		
		m_VecObject->at(i).TabVertices= new float[m_VecObject->at(i).Faces.size()*9];
		m_VecObject->at(i).TabTextures= new float[m_VecObject->at(i).Faces.size()*6];

		for(unsigned int j=0;j<m_VecObject->at(i).Faces.size();j++)//draw all faces
		{
			VecFace.SetX(m_VecObject->at(i).Faces.at(j).vertIndex[0]);
			VecFace.SetY(m_VecObject->at(i).Faces.at(j).vertIndex[1]);
			VecFace.SetZ(m_VecObject->at(i).Faces.at(j).vertIndex[2]);
			//----------------
			//Texture coord
			//----------------
			VecTAB.SetX(m_VecObject->at(i).TexVerts.at(VecFace.GetX()).GetX());
			VecTAB.SetY(m_VecObject->at(i).TexVerts.at(VecFace.GetX()).GetY());

			VecTBC.SetX(m_VecObject->at(i).TexVerts.at(VecFace.GetY()).GetX());
			VecTBC.SetY(m_VecObject->at(i).TexVerts.at(VecFace.GetY()).GetY());

			VecTCA.SetX(m_VecObject->at(i).TexVerts.at(VecFace.GetZ()).GetX());
			VecTCA.SetY(m_VecObject->at(i).TexVerts.at(VecFace.GetZ()).GetY());

			m_VecObject->at(i).TabTextures[0+j*6]=VecTAB.GetX();
			m_VecObject->at(i).TabTextures[1+j*6]=VecTAB.GetY();
			m_VecObject->at(i).TabTextures[2+j*6]=VecTBC.GetX();
			m_VecObject->at(i).TabTextures[3+j*6]=VecTBC.GetY();
			m_VecObject->at(i).TabTextures[4+j*6]=VecTCA.GetX();
			m_VecObject->at(i).TabTextures[5+j*6]=VecTCA.GetY();
			//----------------
			//Vertex coord
			//----------------
			VecX.SetX(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetX());
			VecX.SetY(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetY());
			VecX.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetZ());		

			VecY.SetX(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetX());
			VecY.SetY(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetY());
			VecY.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetZ());

			VecZ.SetX(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetX());
			VecZ.SetY(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetY());
			VecZ.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetZ());

			m_VecObject->at(i).TabVertices[0+j*9]=VecX.GetX();
			m_VecObject->at(i).TabVertices[1+j*9]=VecX.GetY();
			m_VecObject->at(i).TabVertices[2+j*9]=VecX.GetZ();
			m_VecObject->at(i).TabVertices[3+j*9]=VecY.GetX();
			m_VecObject->at(i).TabVertices[4+j*9]=VecY.GetY();
			m_VecObject->at(i).TabVertices[5+j*9]=VecY.GetZ();
			m_VecObject->at(i).TabVertices[6+j*9]=VecZ.GetX();
			m_VecObject->at(i).TabVertices[7+j*9]=VecZ.GetY();
			m_VecObject->at(i).TabVertices[8+j*9]=VecZ.GetZ();
			}
	}
	HasArray=true;
UnGuard
}

void ExCModel3DS::Draw(void)
{
Guard(void ExCModel3DS::Draw(void))
try
{
	ExCVec3D VecAB,VecBC,VecCA,VecFace;
	ExCVec3D VecX,VecY,VecZ;
	bool DrawIt=false;
	ProcessAllAction();
	if(!m_Visible)return;
	if(HasList==false)BuildList(RENDER_TEXTURES);
	if(HasArray==false)BuildArray(RENDER_TEXTURES);
	glPushMatrix();
		//ExCModel::Draw();
		//glTranslatef(m_Position.GetX(),m_Position.GetY(),m_Position.GetZ());
		glRotatef(-90,1,0,0);
		if(m_AlwaysDraw)
		{
			switch(m_RenderMode)
			{
			case RENDER_VERTEX_ARRAY:CallAllArray();break;
			case RENDER_DISPLAY_LIST:CallAllList();break;
			}
			
			
		}else
		{
			//Draw only objet in frustrum
			ExCFrustum Frustrum;
			Frustrum.CalculateFrustum();
			for(unsigned int i=0;i<m_VecObject->size();i++)//draw all objects
			{
				DrawIt=false;
				for(unsigned int j=0;j<m_VecObject->at(i).Faces.size();j++)//draw all faces
				{
					VecFace.SetX(m_VecObject->at(i).Faces.at(j).vertIndex[0]);
					VecFace.SetY(m_VecObject->at(i).Faces.at(j).vertIndex[1]);
					VecFace.SetZ(m_VecObject->at(i).Faces.at(j).vertIndex[2]);
					//----------------
					//Vertex coord
					//----------------
					VecX.SetX(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetX());
					VecX.SetY(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetY());
					VecX.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetZ());		
					VecY.SetX(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetX());
					VecY.SetY(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetY());
					VecY.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetZ());
					VecZ.SetX(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetX());
					VecZ.SetY(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetY());
					VecZ.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetZ());
					VecX=VecX+m_Position;
					VecY=VecY+m_Position;
					VecZ=VecZ+m_Position;
					if(Frustrum.PointInFrustum(VecX.GetX(),VecX.GetY(),VecX.GetZ())){DrawIt=true;}
					if(Frustrum.PointInFrustum(VecY.GetX(),VecY.GetY(),VecY.GetZ())){DrawIt=true;}
					if(Frustrum.PointInFrustum(VecZ.GetX(),VecZ.GetY(),VecZ.GetZ())){DrawIt=true;}
				}
				if(DrawIt)
				{
					switch(m_RenderMode)
					{
					case RENDER_VERTEX_ARRAY:
						//std::cout<<"vertexmode"<<std::endl;
							glDisable(GL_LIGHTING);
							glColor3f(1.0f,1.0f,1.0f);
							ManagerTexture->SetTexture(0,m_VecObject->at(i).Material);
							glTexCoordPointer(2,GL_FLOAT,0,m_VecObject->at(i).TabTextures);
							glEnableClientState(GL_VERTEX_ARRAY);
							glVertexPointer(3,GL_FLOAT,0,m_VecObject->at(i).TabVertices);
							glDrawArrays( GL_TRIANGLES, 0, m_VecObject->at(i).Faces.size()*3 );
							ManagerTexture->ResetMultitexture();
						break;
					case RENDER_DISPLAY_LIST:
						//std::cout<<"listmode"<<std::endl;
						glCallList(m_VecObject->at(i).m_ListId);
						break;
					}
				}
			}
		}
	
	glPopMatrix();
}catch (...) 
{
	std::cout<<"probleme"<<std::endl;
}
UnGuard
}

void ExCModel3DS::CallAllList(void)
{
Guard(void ExCModel3DS::CallAllList(void))
	for(unsigned int i=0;i<m_VecObject->size();i++)//draw all objects
	{
		glCallList(m_VecObject->at(i).m_ListId);
	}
UnGuard
}

void ExCModel3DS::CallAllArray(void)
{
Guard(void ExCModel3DS::CallAllArray(void))
	for(unsigned int i=0;i<m_VecObject->size();i++)//draw all objects
	{
		glDisable(GL_LIGHTING);
		glColor3f(1.0f,1.0f,1.0f);
		ManagerTexture->SetTexture(0,m_VecObject->at(i).Material);
		glTexCoordPointer(2,GL_FLOAT,0,m_VecObject->at(i).TabTextures);
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,0,m_VecObject->at(i).TabVertices);
		glDrawArrays( GL_TRIANGLES, 0, m_VecObject->at(i).Faces.size()*3 );
		ManagerTexture->ResetMultitexture();
	}
UnGuard
}


void ExCModel3DS::BuildList(int Rendu)
{
Guard(void ExCModel3DS::BuildList(int Rendu))
		
//---------------------------------------------------
		ExCVec3D VecAB,VecBC,VecCA,VecFace;
		ExCVec3D VecX,VecY,VecZ;
		ExCVec2D VecTAB,VecTBC,VecTCA;
		glPushMatrix();
		//ExCModel::Draw();
		glDisable(GL_LIGHTING);
		for(unsigned int i=0;i<m_VecObject->size();i++)//draw all objects
		{
			try
			{
				glDeleteLists(m_VecObject->at(i).m_ListId,1);	//delete old list
				m_VecObject->at(i).m_ListId=glGenLists(1);	//Ask for a new free list
				glNewList(m_VecObject->at(i).m_ListId,GL_COMPILE);
				for(unsigned int j=0;j<m_VecObject->at(i).Faces.size();j++)//draw all faces
				{
					VecFace.SetX(m_VecObject->at(i).Faces.at(j).vertIndex[0]);
					VecFace.SetY(m_VecObject->at(i).Faces.at(j).vertIndex[1]);
					VecFace.SetZ(m_VecObject->at(i).Faces.at(j).vertIndex[2]);
					//----------------
					//Texture coord
					//----------------
					VecTAB.SetX(m_VecObject->at(i).TexVerts.at(VecFace.GetX()).GetX());
					VecTAB.SetY(m_VecObject->at(i).TexVerts.at(VecFace.GetX()).GetY());

					VecTBC.SetX(m_VecObject->at(i).TexVerts.at(VecFace.GetY()).GetX());
					VecTBC.SetY(m_VecObject->at(i).TexVerts.at(VecFace.GetY()).GetY());

					VecTCA.SetX(m_VecObject->at(i).TexVerts.at(VecFace.GetZ()).GetX());
					VecTCA.SetY(m_VecObject->at(i).TexVerts.at(VecFace.GetZ()).GetY());
					//----------------
					//Vertex coord
					//----------------

					VecX.SetX(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetX());
					VecX.SetY(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetY());
					VecX.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetX()).GetZ());		

					VecY.SetX(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetX());
					VecY.SetY(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetY());
					VecY.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetY()).GetZ());

					VecZ.SetX(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetX());
					VecZ.SetY(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetY());
					VecZ.SetZ(m_VecObject->at(i).Verts.at(VecFace.GetZ()).GetZ());
	
					ManagerTexture->SetCurrentObject(m_VecObject->at(i).Material);

					glColor3f(1.0f,1.0f,1.0f);
					glEnable(GL_TEXTURE_2D);
					glBegin(GL_TRIANGLES);
						glTexCoord2f(VecTAB.GetX(),VecTAB.GetY());
						glVertex3fv(VecX.m_Vector);			
						glTexCoord2f(VecTBC.GetX(),VecTBC.GetY());
						glVertex3fv(VecY.m_Vector);			
						glTexCoord2f(VecTCA.GetX(),VecTCA.GetY());
						glVertex3fv(VecZ.m_Vector);			
					glEnd();
					glDisable(GL_TEXTURE_2D);
					
				}
				glEndList();
			}catch (...) 
			{
				std::cout<<"error building list"<<std::endl;
			}

		}
		glPopMatrix();
//---------------------------------------------------
		
	HasList=true;	
	//std::cout<<"building list ok"<<//std::endl;
UnGuard
}

ExCAction ExCModel3DS::InputAction(ExCAction Action)
{
	//std::cout<<"MODEL"<<Action;
	switch(Action.m_Action) 
	{
	case NEXT_FRAME:
		NextFrame();
		break;
	case PREVIOUS_FRAME:
		break;
	case SET_CURENT_FRAME:
		break;
	case START_ACTION:
		StartAction(Action.m_Param);
		break;
	case STOP_ACTION:
		StopAction(Action.m_Param);
		break;
	case TURN_LEFT:
		StartAction("TURN_LEFT");
		break;
	case TURN_RIGHT:
		StartAction("TURN_RIGHT");
	case LOOK_UP:
		StartAction(Action.m_Param);
		break;
	case LOOK_DOWN:
		StartAction(Action.m_Param);
		break;
	case MODEL_SET_POS_X:
		std::cout<<"MODEL"<<Action<<atof(Action.m_Param.data());
		m_Position.SetX(atof(Action.m_Param.data()));
		break;
	case MODEL_SET_POS_Y:
		m_Position.SetY(atof(Action.m_Param.data()));
		break;
	case MODEL_SET_POS_Z:
		m_Position.SetZ(atof(Action.m_Param.data()));
		break;
	case MODEL_SET_ANGLE_X:
		m_Angle.SetX(atof(Action.m_Param.data()));
		break;
	case MODEL_SET_ANGLE_Y:
		m_Angle.SetY(atof(Action.m_Param.data()));
		break;
	case MODEL_SET_ANGLE_Z:
		m_Angle.SetZ(atof(Action.m_Param.data()));
		break;
	case MODEL_START_ROTATE_Y_DOWN:
		StartAction("TURN_RIGHT");
		break;
	case MODEL_STOP_ROTATE_Y_DOWN:
		StopAction("TURN_RIGHT");
		if(!IsAction("RUN")){StartAction("IDLE");}
		break;
	case MODEL_START_ROTATE_Y_UP:
		StartAction("TURN_LEFT");
		break;
	case MODEL_STOP_ROTATE_Y_UP:
		StopAction("TURN_LEFT");
		if(!IsAction("RUN")){StartAction("IDLE");}
		break;
	case MODEL_START_ROTATE_Z_DOWN:
		StartAction("LOOK_UP");
		break;
	case MODEL_STOP_ROTATE_Z_DOWN:
		StopAction("LOOK_UP");
		break;
	case MODEL_START_ROTATE_Z_UP:
		StartAction("LOOK_DOWN");
		break;
	case MODEL_STOP_ROTATE_Z_UP:
		StopAction("LOOK_DOWN");
		break;
	case MODEL_START_ROTATE_X_DOWN:
		StartAction("X_DOWN");
		break;
	case MODEL_STOP_ROTATE_X_DOWN:
		StopAction("X_DOWN");
		break;
	case MODEL_START_ROTATE_X_UP:
		StartAction("X_UP");
		break;
	case MODEL_STOP_ROTATE_X_UP:
		StopAction("X_UP");
		break;
	case MODEL_START_MOVE_FORWARD:
		StartAction("RUN");
		m_Acceleration=m_Acceleration+0.01;
		break;
	case MODEL_STOP_MOVE_FORWARD:
		StopAction("RUN");
		StartAction("IDLE");
		m_Acceleration.SetValue(0.0f,0.0f,0.0f);
		break;
	case MODEL_JUMP:
		StartAction("JUMP");
		break;
	case MODEL_SET_ACTION:
		break;
	case MODEL_STOP_ALL:
		m_VecAction.clear();
		m_Velocity.SetValue(0.0f,0.0f,0.0f);
		m_Acceleration.SetValue(0.0f,0.0f,0.0f);
		break;
	case MODEL_SHOW_COLLISION_SPHERE:

		break;
	case MODEL_START_STRAFE_LEFT:
		StartAction("STRAFE_LEFT");
		break;
	case MODEL_STOP_STRAFE_LEFT	:
		StopAction("STRAFE_LEFT");
		break;
	case MODEL_START_STRAFE_RIGHT:
		StartAction("STRAFE_RIGHT");
		break;
	case MODEL_STOP_STREFA_RIGHT:
		StopAction("STRAFE_RIGHT");
		break;
	case MODEL_TOGGLE_VISIBLESTATE:
		SetVisibleState(!GetVisibleState());
		//std::cout<<m_ObjectName<<" toggle"<<std::endl;
		break;
	case MODEL_HIDE:
		SetVisibleState(false);
		//std::cout<<m_ObjectName<<" hide"<<std::endl;
		break;
	case MODEL_SHOW:
		SetVisibleState(true);
		//std::cout<<m_ObjectName<<" show"<<std::endl;
		break;
	case MODEL_TOGGLE_ALWAYS_DRAW:
		m_AlwaysDraw=!m_AlwaysDraw;
		break;
	case MODEL_ALWAYS_DRAW_ON:
		m_AlwaysDraw=true;
		break;
	case MODEL_ALWAYS_DRAW_OFF:
		m_AlwaysDraw=false;
		break;
	case MODEL_SET_RENDER_MODE:
		m_RenderMode=atoi(Action.m_Param.data());
		break;
	}
	return NOTHING;
}

void ExCModel3DS::Process(std::string Action)
{
	Guard(void ExCModel3DS::Process(std::string Action))
		if(m_Angle.GetX()<0)m_Angle.SetX(359);
	if(m_Angle.GetX()>359)m_Angle.SetX(0);
	if(m_Angle.GetY()<0)m_Angle.SetY(359);
	if(m_Angle.GetY()>359)m_Angle.SetY(0);
	if(m_Angle.GetZ()<0)m_Angle.SetZ(359);
	if(m_Angle.GetZ()>359)m_Angle.SetZ(0);
	//process action
	if(Action=="RUN")
	{
		//m_Position=m_Target;
		//return;
		//m_Velocity.SetX(0.01f);
	}
	if(Action=="STRAFE_LEFT")
	{
		float angle;
		angle=m_Angle.GetY()+90;
		if(angle>360)angle=angle-360;
		m_Position=m_Position+ExCVec3D(Cos[(int)angle],0.0f,Sin[(int)angle]);
		return;
	}
	if(Action=="STRAFE_RIGHT")
	{
		float angle;
		angle=m_Angle.GetY()+90;
		if(angle>360)angle=angle-360;
		m_Position=m_Position-ExCVec3D(Cos[(int)angle],0.0f,Sin[(int)angle]);
		return;
	}

	if(Action=="TURN_LEFT"){m_Angle.DecY(2);return;}
	if(Action=="TURN_RIGHT"){m_Angle.IncY(2);return;}
	if(Action=="LOOK_UP"){m_Angle.IncZ(2);return;}
	if(Action=="LOOK_DOWN"){m_Angle.DecZ(2);return;}
	if(Action=="X_UP"){m_Angle.IncX(2);return;}
	if(Action=="X_DOWN"){m_Angle.DecX(2);return;}
	if(Action=="JUMP")
	{
		if(m_CurrentFrames=72)
		{
			StopAction("JUMP");
			if(!IsAction("RUN")){StartAction("IDLE");}
		}
	}
	UnGuard
}
void ExCModel3DS::ProcessAllAction(void)
{
	Guard(void ExCModel3DS::ProcessAllAction(void))
		for(unsigned int i=0;i< m_VecAction.size();i++)
		{
			Process(m_VecAction.at(i));	
		}
		UnGuard
}

void ExCModel3DS::StopAction(std::string	 Action)
{
	Guard(void ExCModel3DS::StopAction(std::string	 Action))
		for(m_IVecAction= m_VecAction.begin();m_IVecAction!= m_VecAction.end();m_IVecAction++)
		{
			if(strcmp(m_IVecAction->data(),Action.data())==0)
			{
				m_VecAction.erase(m_IVecAction);
				return;
			}
		}	
		UnGuard
}

bool ExCModel3DS::IsAction(std::string Action)
{
	Guard(bool ExCModel3DS::IsAction(std::string Action))
		for(m_IVecAction= m_VecAction.begin();m_IVecAction!= m_VecAction.end();m_IVecAction++)
		{
			if(strcmp(m_IVecAction->data(),Action.data())==0)
			{
				return true;
			}
		}
		return false;
		UnGuard
}
void ExCModel3DS::StartAction(std::string	 Action)
{
	Guard(void ExCModel3DS::StartAction(std::string	 Action))
		m_VecAction.push_back(Action);
	m_CurrentAction=Action;
	UnGuard
}


bool ExCModel3DS::Load(std::string FileName)	    
{
Guard(bool ExCModel3DS::Load(std::string FileName))

	m_VecObject= new std::vector<t3DObject> ;
	numOfObjects=0;
	numOfMaterials=0;
	m_VecMaterials.clear();
	m_VecObject->clear();
	HasList=false;
	unsigned int version=0;
	int buffer[50000] = {0};
	char bufferc[255];memset(bufferc,0,255);

	
	m_filePtr = fopen(FileName.data(), "rb");
    if (m_filePtr == NULL) 
	{
		throw ExCExpFileNotFound();
		return false;
	}
	tChunk *chunk;
	chunk = new tChunk;
	ReadChunk(chunk);
	//------------------------------------------------------------------------------
	if(chunk->ID==PRIMARY)
	{
		//std::cout<<"Primary chunk file lenght:"<<chunk->length<<//std::endl;
		m_CurrentChunk = new tChunk;
		while (chunk->bytesRead < chunk->length)
		{
	 		ReadChunk(m_CurrentChunk);
			switch(m_CurrentChunk->ID)
			{
			case FILEVERSION:
				m_CurrentChunk->bytesRead += fread(&version, 1,m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_filePtr);
				//std::cout<<"Read FILEVERSION :"<<version<<//std::endl;
				break;
			case OBJECTINFO:
				//std::cout<<"Read OBJECTINFO"<<//std::endl;
				ReadObjectInfo(m_CurrentChunk);
				break;
			case EDITKEYFRAME:
				//std::cout<<"Read EDITKEYFRAME"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			default:
				//std::cout<<"Skip unused ,Chunk ID:"<<//std::hex<<m_CurrentChunk->ID<<" Chunk Lenght:"<<//std::dec<<m_CurrentChunk->length<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			}
			chunk->bytesRead += m_CurrentChunk->bytesRead;
		}
  		delete m_CurrentChunk;
		m_CurrentChunk = chunk;
	}//end of if(chunk->ID==PRIMARY)
	//------------------------------------------------------------------------------
	fclose(m_filePtr);
	//BuildArray(0);
	return true;
UnGuard
}

void ExCModel3DS::ReadObjectInfo(tChunk *chunk)
{
Guard(void ExCModel3DS::ReadObjectInfo(tChunk *chunk))
		int buffer[50000] = {0};
		char bufferc[255],b;
		std::string BuffObject;
		m_CurrentChunk = new tChunk;
		while (chunk->bytesRead < chunk->length)
		{
	 		ReadChunk(m_CurrentChunk);
			switch(m_CurrentChunk->ID)
			{
			case MATERIAL:
				//std::cout<<"	Read MATERIAL"<<//std::endl;
				ReadObjectMaterial(m_CurrentChunk);
				break;
			case OBJECT:
				memset(bufferc,0,255);
				//m_CurrentChunk->bytesRead += 8;
				//m_CurrentChunk->bytesRead += fread(&bufferc, 1,8, m_filePtr);
				////std::cout<<m_CurrentChunk->length - m_CurrentChunk->bytesRead<<//std::endl;
				BuffObject.erase(BuffObject.begin(),BuffObject.end());
				do
				{
					m_CurrentChunk->bytesRead += fread(&b, 1, sizeof(char), m_filePtr);
					if(b!=0)BuffObject=BuffObject+b;
				}while(b!=0);
				//std::cout<<"	Read OBJECT :"<<BuffObject<<//std::endl;
				ReadObject(m_CurrentChunk);
				break;
			case MESH_VERSION:
				//std::cout<<"	Read MESH_VERSION"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MASTER_SCALE:
				//std::cout<<"	Read MASTER_SCALE"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			default:
				//std::cout<<"	Skip unused ,Chunk ID:"<<//std::hex<<m_CurrentChunk->ID<<" Chunk Lenght:"<<//std::dec<<m_CurrentChunk->length<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			}
			chunk->bytesRead += m_CurrentChunk->bytesRead;
		}
  		delete m_CurrentChunk;
		m_CurrentChunk = chunk;
UnGuard
}
void ExCModel3DS::ReadObject(tChunk *chunk)
{
Guard(void ExCModel3DS::ReadObject(tChunk *chunk))
	int buffer[50000] = {0};
	t3DObject *pObject;
	pObject = new t3DObject;
	m_CurrentChunk = new tChunk;
	while (chunk->bytesRead < chunk->length)
	{
	 	ReadChunk(m_CurrentChunk);
		switch(m_CurrentChunk->ID)
		{
		case OBJECT_MESH:		
			//std::cout<<"		Read object OBJECT_MESH"<<//std::endl;
			ReadObject(m_CurrentChunk);
			break;
		case OBJECT_VERTICES:	
			//std::cout<<"			Read object OBJECT_VERTICES"<<//std::endl;
			//Skip(m_CurrentChunk);
			ReadVertices(pObject,m_CurrentChunk);
			break;
    	case OBJECT_FACES:		
			//std::cout<<"			Read object OBJECT_FACES"<<//std::endl;
			ReadFace(pObject,m_CurrentChunk);
			break;
    	case OBJECT_MATERIAL:	

			//std::cout<<"			Read object OBJECT_MATERIAL"<<//std::endl;
			ReadObjectMaterial(pObject,m_CurrentChunk);
			break;
    	case OBJECT_UV:
			//std::cout<<"			Read object OBJECT_UV"<<//std::endl;
			ReadUVCoordinates(pObject,m_CurrentChunk);
			break;
		case OBJECT_MESH_MATRIX:
			//std::cout<<"			Read object OBJECT_MESH_MATRIX"<<//std::endl;
			Skip(m_CurrentChunk);
			break;
		default:
			//std::cout<<"			Skip unused ,Chunk ID:"<<//std::hex<<m_CurrentChunk->ID<<" Chunk Lenght:"<<//std::dec<<m_CurrentChunk->length<<//std::endl;
			Skip(m_CurrentChunk);
			break;
		}
		chunk->bytesRead += m_CurrentChunk->bytesRead;
	}
	
	m_VecObject->push_back(*pObject);
  	delete m_CurrentChunk;
	m_CurrentChunk = chunk;
UnGuard
}

void ExCModel3DS::ReadObjectMaterial(tChunk *chunk)
{
Guard(void ExCModel3DS::ReadObjectMaterial(tChunk *chunk))
		int buffer[50000] = {0};
		char bufferc[255];
		m_CurrentChunk = new tChunk;
		while (chunk->bytesRead < chunk->length)
		{
	 		ReadChunk(m_CurrentChunk);
			switch(m_CurrentChunk->ID)
			{
			case MATNAME:							
				memset(bufferc,0,255);			
				m_CurrentChunk->bytesRead += fread(bufferc, 1, m_CurrentChunk->length - m_CurrentChunk->bytesRead, m_filePtr);
				//std::cout<<"		Read MATNAME:"<<bufferc<<//std::endl;
				break;
			case MATAMBIENTCOLOR:						
				//std::cout<<"		Read MATAMBIENTCOLOR"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATDIFFUSE:						
				//std::cout<<"		Read MATDIFFUSE"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATSPECULAR:						
				//std::cout<<"		Read MATSPECULAR"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATSHININESS:						
				//std::cout<<"		Read MATSHININESS"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATSHININESSSTR:						
				//std::cout<<"		Read MATSHININESSSTR"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATTRANSPARENCY:						
				//std::cout<<"		Read MATTRANSPARENCY"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATTRANSFALLOFF:						
				//std::cout<<"		Read MATTRANSFALLOFF"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATREFLECTBLUR:						
				//std::cout<<"		Read MATREFLECTBLUR"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATTWOSIDED:						
				//std::cout<<"		Read MATTWOSIDED"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATTRANSPARENCYADD:						
				//std::cout<<"		Read MATTRANSPARENCYADD"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATSELFILUM:						
				//std::cout<<"		Read MATSELFILUM"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATWIREON:						
				//std::cout<<"		Read MATWIREON"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATWIRETHICKNESS:						
				//std::cout<<"		Read MATWIRETHICKNESS"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATFACEMAP:						
				//std::cout<<"		Read MATFACEMAP"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATTRANSFALLOFFIN:						
				//std::cout<<"		Read MATTRANSFALLOFFIN"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATSOFTEN:						
				//std::cout<<"		Read MATSOFTEN"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MAT3DWIRETHICKNESS:						
				//std::cout<<"		Read MAT3DWIRETHICKNESS"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATTYPE:							// This is the header for the texture info
				//std::cout<<"		Read MATTYPE"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATMAP:							// This is the header for the texture info
				//std::cout<<"		Read MATMAP"<<//std::endl;
				ReadObjectMaterial(m_CurrentChunk);
				break;
			case MATMAPFILE:						
				//std::cout<<"		Read MATMAPFILE"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATMAPOPTION:						
				//std::cout<<"		Read MATMAPOPTION"<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			case MATMAPFILTERINGBLUR:						
				//std::cout<<"		Read MATMAPFILTERINGBLUR"<<//std::endl;
				//Skip(m_CurrentChunk);
				Skip(m_CurrentChunk);
				break;
			default:
				//std::cout<<"		Skip unused ,Chunk ID:"<<//std::hex<<m_CurrentChunk->ID<<" Chunk Lenght:"<<//std::dec<<m_CurrentChunk->length<<//std::endl;
				Skip(m_CurrentChunk);
				break;
			}
			chunk->bytesRead += m_CurrentChunk->bytesRead;
		}
  		delete m_CurrentChunk;
		m_CurrentChunk = chunk;
UnGuard
}



void ExCModel3DS::ReadChunk(tChunk *chunk)
{
Guard(void ExCModel3DS::tChunk ReadChunk(tChunk *chunk))
	////std::cout<<"File Position bef:"<<ftell(m_filePtr)<<//std::endl;
	chunk->bytesRead = fread(&chunk->ID, 1, 2, m_filePtr);
	chunk->bytesRead += fread(&chunk->length, 1, 4, m_filePtr);
	////std::cout<<"Chunk ID:"<<//std::hex<<chunk->ID<<//std::endl;
	////std::cout<<"Chunk Lenght:"<<//std::dec<<chunk->length<<//std::endl;
	////std::cout<<"File Position:"<<ftell(m_filePtr)<<//std::endl;
UnGuard
}

void ExCModel3DS::Skip(tChunk *chunk)
{
Guard(void ExCModel3DS::tChunk Skip(tChunk *chunk))
	int buffer[50000] = {0};	
	////std::cout<<"Skip :"<< chunk->length - chunk->bytesRead<<//std::endl;
	chunk->bytesRead += fread(buffer, 1, chunk->length - chunk->bytesRead, m_filePtr);
UnGuard
}

void ExCModel3DS::ReadVertices(t3DObject *pObject,tChunk *chunk)
{
Guard(void ExCModel3DS::ReadVertices(t3DObject *pObject,tChunk *chunk))
	int buffer[50000] = {0};		
	// Read in the number of vertices (int)
	unsigned short vert;
	chunk->bytesRead += fread(&vert, 1,sizeof(unsigned short), m_filePtr);
	pObject->numOfVerts=vert;
	////std::cout<<"Number of vertex"<<vert<<//std::endl;
	float fl;
	ExCVec3D vec;
	for(int i=0;i<vert;i++)
	{
		chunk->bytesRead += fread(&fl, 1,sizeof(float), m_filePtr);
		vec.SetX(fl);
		chunk->bytesRead += fread(&fl, 1,sizeof(float), m_filePtr);
		vec.SetY(fl);
		chunk->bytesRead += fread(&fl, 1,sizeof(float), m_filePtr);
		vec.SetZ(fl);
		////std::cout<<"vec:"<<vec<<//std::endl;
		pObject->Verts.push_back(vec);
	}
	Skip(chunk);
UnGuard
}

void ExCModel3DS::ReadFace(t3DObject *pObject,tChunk *chunk)
{
Guard(void ExCModel3DS::ReadFace(t3DObject *pObject,tChunk *chunk))
	int buffer[50000] = {0};		
	// Read in the number of vertices (int)
	tFace stFace;
	unsigned short face,index;
	chunk->bytesRead += fread(&face, 1,sizeof(unsigned short), m_filePtr);
	pObject->numOfFaces=face;
	////std::cout<<"Number of Face :"<<face<<//std::endl;	
	
	// Go through all of the faces in this object
	for(int i = 0; i <face; i++)
	{
		// Next, we read in the A then B then C index for the face, but ignore the 4th value.
		// The fourth value is a visibility flag for 3D Studio Max, we don't care about this.
		for(int j = 0; j < 4; j++)
		{
			// Read the first vertice index for the current face 
			chunk->bytesRead += fread(&index, 1, sizeof(unsigned short), m_filePtr);

			if(j < 3)
			{
				// Store the index in our face structure.
				//pObject->pFaces[i].vertIndex[j] = index;
				stFace.vertIndex[j]=index;
			}
		}
		////std::cout<<"Face A:"<<stFace.vertIndex[0]<<" B:"<<stFace.vertIndex[1]<<" C:"<<stFace.vertIndex[2]<<//std::endl;
		pObject->Faces.push_back(stFace);
	}
	char b=0;
	std::string Material;
	m_CurrentChunk = new tChunk;
	while (chunk->bytesRead < chunk->length)
	{
	 	ReadChunk(m_CurrentChunk);
		switch(m_CurrentChunk->ID)
		{
		case OBJECT_MATERIAL:						
			//std::cout<<"				Read object face OBJECT_MATERIAL"<<//std::endl;
			do
			{
				m_CurrentChunk->bytesRead += fread(&b, 1, sizeof(char), m_filePtr);
				if(b!=0)Material=Material+b;
			}while(b!=0);
			////std::cout<<Material<<//std::endl;
			pObject->Material=Material;
			//std::cout<<"#"<<Material<<"#"<<//std::endl;
			ManagerTexture->Load(Material);
			Skip(m_CurrentChunk);
			break;
		case OBJECT_SMOOTH_GROUP:						
			//std::cout<<"				Read object face OBJECT_SMOOTH_GROUP"<<//std::endl;
			Skip(m_CurrentChunk);
			break;
       	default:
			//std::cout<<"				Skip unused ,Chunk ID:"<<//std::hex<<m_CurrentChunk->ID<<" Chunk Lenght:"<<//std::dec<<m_CurrentChunk->length<<//std::endl;
			Skip(m_CurrentChunk);
			break;
		}
		chunk->bytesRead += m_CurrentChunk->bytesRead;
	}
  	delete m_CurrentChunk;
	m_CurrentChunk = chunk;


	
UnGuard
}

void ExCModel3DS::ReadUVCoordinates(t3DObject *pObject,tChunk *chunk)
{
Guard(void ExCModel3DS::ReadUVCoordinates(t3DObject *pObject,tChunk *chunk))
	int buffer[50000] = {0};		
	// Read in the number of vertices (int)
	unsigned short vert;
	chunk->bytesRead += fread(&vert, 1,sizeof(unsigned short), m_filePtr);
	pObject->numTexVertex=vert;
	////std::cout<<"Number of vertex"<<vert<<//std::endl;
	float fl;
	ExCVec2D vec;
	for(int i=0;i<vert;i++)
	{
		chunk->bytesRead += fread(&fl, 1,sizeof(float), m_filePtr);
		vec.SetX(fl);
		chunk->bytesRead += fread(&fl, 1,sizeof(float), m_filePtr);
		vec.SetY(fl);
		////std::cout<<"vec:"<<vec<<//std::endl;
		pObject->TexVerts.push_back(vec);
	}
	Skip(chunk);
UnGuard
}

void ExCModel3DS::ReadObjectMaterial(t3DObject *pObject,tChunk *chunk)
{
Guard(void ExCModel3DS::ReadObjectMaterial(tChunk *chunk))
	char b=0;
	std::string Material;
	do
	{
		chunk->bytesRead += fread(&b, 1, sizeof(char), m_filePtr);
		Material=Material+b;
	}while(b!=0);
	//std::cout<<Material<<//std::endl;
	Skip(chunk);			
UnGuard
}