/*=========================================================================
*
* ModLib.c	- library functions for geometric objects
*
* Version			1.0
* Revision date
*
*=======================================================================*/
#include "ModLib.h"

#include <time.h>

#include "conventi.h"
#include "defines.h"
#include "print.h"
#include "system.h"

#include "ModSave.h"


//--- Global defines --------------------------------------------------------

MLT_tdstGeometricObject **g_hGeometricInFile	= NULL;
long					  g_lGeometricIndex		= 0;



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


/****************************************************************************
*		Description:	load mod file in library
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vLoadModFileInLib ()
{
  SCR_tdst_Cxt_Values	*p_stVal;
  xString				sDirectory;
  xString				szFileName;

  // save directory
  GetCurrentDirectory(256, sDirectory);

  //Inits 
  sprintf(szFileName, "%s.mod", g_sFileIn);

  p_stVal = SCR_fnp_st_RdL0_AnalyseSection(szFileName, SCR_CDF_uw_Anl_ForceAnalyse);

  g_hGeometricInFile = (MLT_tdstGeometricObject **)SCR_M_ul_RdL0_ExtractLongValue(p_stVal,0);
  g_lGeometricIndex = (long)SCR_M_ul_RdL0_ExtractLongValue(p_stVal,1);

  // restore directory
  SetCurrentDirectory(sDirectory); 
}

/****************************************************************************
*		Description:	save library in Mod file
*
*		Parameters:		bPhy	: flag to save PHY 
*						bTbl	: flag to save TBL
*						bZoo	: flag to save ZOO
*						bVse	: flag to save VSE
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vSaveLibInModFile (BOOL bPhy, BOOL bTbl, BOOL bZoo, BOOL bVse)
{
  SCR_tdst_File_Description	stFile;
  xString sDate, sTime, mes, sComment;
  long i;

  sprintf(stFile.a_szFileName,"%s.mod", g_sFileIn);
  
  // to delete the file
  remove(stFile.a_szFileName);

  strcpy(stFile.a_szOpenFileName, stFile.a_szFileName);
  stFile.p_stHandle = (SCR_tdst_File_Handle*)malloc(sizeof(SCR_tdst_File_Handle));
	stFile.p_stHandle->xHandle = (FILE*)_open(stFile.a_szFileName, O_WRONLY | O_CREAT | _O_TEXT, S_IREAD | S_IWRITE);
	stFile.p_stHandle->p_cBase = stFile.p_stHandle->p_cCurrent = NULL;
	stFile.p_stHandle->iCnt = 0;
  stFile.d_stFirstPage = stFile.d_stLastPage = stFile.d_stCurPage = NULL;
	stFile.iCurPosInPage = 0;
  if(stFile.p_stHandle->xHandle == 0)
  {
	  MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't open file %s", stFile.a_szFileName);
	  return;
  }
  
  SCR_M_SvL0_SaveScriptFileHeader(&stFile);
  sprintf(sComment, ".MOD (graphic Module) : %s", stFile.a_szFileName);
  SCR_M_SvL0_SaveComment(&stFile, sComment);
  SCR_M_SvL0_SaveBlankLine(&stFile);
  sprintf(sComment, "Generated by Max23Dos Moulinette");
  SCR_M_SvL0_SaveComment(&stFile, sComment);
  SCR_M_SvL0_SaveBlankLine(&stFile);
  _strtime(sTime);
  _strdate(sDate);
  sprintf(sComment, "Created date : %s %s", sDate, sTime);
  SCR_M_SvL0_SaveComment(&stFile, sComment);
  SCR_M_SvL0_SaveBlankLine(&stFile);
  sprintf(sComment, "Version directive, the version number is stored in file result 0");
  SCR_M_SvL0_SaveComment(&stFile, sComment);
  SCR_M_SvL0_SaveDirective(&stFile, M_SetCurrentFileDouble,SCR_CC_C_Cfg_NoChar);
  SCR_fn_v_SvL0_SaveParameters_MP(&stFile, SCR_EF_SvL0_Scanf, 3, "%d,%.1f", 0, 5.0);
  SCR_M_SvL0_SaveBlankLine(&stFile);
  sprintf(sComment, "Unit directive, the unit is stored in file result 1");
  SCR_M_SvL0_SaveComment(&stFile, sComment);
  sprintf(sComment, "And correspond to the value of one unit exprimed in meter");
  SCR_M_SvL0_SaveComment(&stFile, sComment);
  SCR_M_SvL0_SaveDirective(&stFile, M_SetCurrentFileDouble,SCR_CC_C_Cfg_NoChar);
  SCR_fn_v_SvL0_SaveParameters_MP(&stFile, SCR_EF_SvL0_Scanf, 3, "%d,%.1f", 1, 1.0);
  SCR_M_SvL0_SaveBlankLine(&stFile);

  sprintf(mes, "Edit-ListModifGeometric%s", SCR_CC_sz_Cfg_SectionIdMark);
  SCR_M_SvL0_SaveBeginSection(&stFile, mes, SCR_CC_C_Cfg_EOL);
  SCR_M_SvL0_SaveEndSection(&stFile, SCR_CC_C_Cfg_EOL);
  
  g_iNbInstancesSaved = 0;
  for(i=0; i<g_lGeometricIndex; i++)
    MLT_vSaveGeometricObject(&stFile, g_hGeometricInFile[i], bPhy, bTbl, bZoo, bVse);

  _close((int)stFile.p_stHandle->xHandle);
  free(stFile.p_stHandle);
}


/****************************************************************************
*		Description:	return the number of object loaded
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
long MLT_lGetNumberObjectInLib()
{
  return g_lGeometricIndex;
}

/****************************************************************************
*		Description:	return the object from the index in list
*
*		Parameters:		lIndex	: index of the object
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
MLT_tdstGeometricObject *MLT_lGetObjectFromLib(long lIndex)
{
  if(lIndex < g_lGeometricIndex)
    return g_hGeometricInFile[lIndex];
  else
    return NULL;
}



/****************************************************************************
*		Description:	return the object from the name
*
*		Parameters:		sGeometric	: name of object to search
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
MLT_tdstGeometricObject *MLT_pFindInLib(char *sGeometric)
{
  int i;

  for (i=0; i<g_lGeometricIndex; i++)
  {
    if (g_hGeometricInFile[i] != NULL)
	{
      if(stricmp(sGeometric, g_hGeometricInFile[i]->sName) == 0)
        return g_hGeometricInFile[i];
	}
  }

  return NULL;
}
/****************************************************************************
*		Description:	return the object with the same forme and the same number of Lod
*
*		Parameters:		sObjName	: name of object to search
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
MLT_tdstGeometricObject *MLT_pFindAlmostInLib (char *sObjName)
{
  int		i;
  long		lNoPhy, lNoLod;
  long		lNoPhy2, lNoLod2;
  xString	sFile, sAction, sIdent;
  xString	sFile2, sAction2, sIdent2;
  xString	sForme, sHabillage, sName;
  xString	sForme2, sHabillage2, sName2;

  // get minimal name of geometric object
  SCR_fn_v_RdL0_SplitSectionName(sObjName, sFile, sAction, sIdent);
  MLT_vSplitModuleSectionName(sIdent, sForme, sHabillage, &lNoPhy, &lNoLod, sName);
  if (strstr(sIdent, "!")&&(!strstr(sIdent, "!nocol")) &&(!strstr(sIdent, "!NOCOL"))) 
	  strcat(sForme, "!");

  // check each object of the library
  for (i=0; i<g_lGeometricIndex; i++)
  {
    if(g_hGeometricInFile[i] != NULL) 
	{
	  // get its minimal name
	  SCR_fn_v_RdL0_SplitSectionName(g_hGeometricInFile[i]->sName, sFile2, sAction2, sIdent2);
      MLT_vSplitModuleSectionName(sIdent2, sForme2, sHabillage2, &lNoPhy2, &lNoLod2, sName2);
	  if (strstr(sIdent2, "!")&&(!strstr(sIdent, "!nocol")) &&(!strstr(sIdent, "!NOCOL"))) 
		  strcat(sForme2, "!");
	}

    // compare the parameters
	if (g_hGeometricInFile[i] != NULL) 
	{
	  // same form
      if(stricmp(sForme, sForme2) == 0) 
	  {
        // same number of LOD
		if(lNoLod2 == lNoLod) 
          return g_hGeometricInFile[i];
	  }
	}
  }

  // object was not found
  return NULL;
}

/****************************************************************************
*		Description:	return the object with the given name in the given library
*
*		Parameters:		sGeometric			: name of object to search
*						p_xGeometricInFile	: library
*						xNbGeometric		: number of element in the library
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
MLT_tdstGeometricObject *MLT_pFindInGivenLib(char *sGeometric, MLT_tdstGeometricObject **p_xGeometricInFile, long xNbGeometric)
{
  int i;

  for (i=0; i<xNbGeometric; i++)
  {
    if(p_xGeometricInFile[i] != NULL)
	{
      if(stricmp(sGeometric, p_xGeometricInFile[i]->sName) == 0)
        return p_xGeometricInFile[i];
	}
  }

  return NULL;
}


/****************************************************************************
*		Description:	return the list of objects with the same name
*
*		Parameters:		sObjName	: name of object to search
*						h_stObj		: list to fill
*						p_lNbObj	: returns the number of objects found
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vRequestObjInLib(xString sObjName, MLT_tdstGeometricObject ***h_stObj, long *p_lNbObj)
{
  long i;

  // init list
  *h_stObj = NULL;
  *p_lNbObj = 0;

  // check all library
  for (i=0; i<g_lGeometricIndex; i++)
  {
    if (g_hGeometricInFile[i] != NULL)
	{
      // check the name of the geometric object
	  if (stricmp(sObjName, g_hGeometricInFile[i]->sName) == 0)
      {
        *h_stObj = (MLT_tdstGeometricObject**)realloc(*h_stObj,((*p_lNbObj)+1)*sizeof(MLT_tdstGeometricObject*));
        (*h_stObj)[*p_lNbObj]=g_hGeometricInFile[i];
        (*p_lNbObj)++;
      }
	}
  }
}



/****************************************************************************
*		Description:	return all the objects with the same forme and the same mapping
*
*		Parameters:		sObjName	: name of object to search
*						h_stObj		: list to fill
*						p_lNbObj	: returns the number of objects found
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vRequestAlmostInLib(xString sObjName, MLT_tdstGeometricObject ***h_stObj, long *p_lNbObj)
{
  xString	sFile, sAction, sIdent, sName;
  xString	sForme2, sHabillage2;
  xString	sForme, sHabillage;
  long		lNoPhy, lNoLod;
  long		i;

  // init list
  *h_stObj = NULL;
  *p_lNbObj = 0;

  // get the minimal name
  MLT_vSplitModuleSectionName(sObjName, sForme2, sHabillage2, &lNoPhy, &lNoLod, sName);

  // check all library
  for(i=0; i<g_lGeometricIndex; i++)
  {
    if (g_hGeometricInFile[i] != NULL)
    {
      // get minimal name of the geometric object
	  SCR_fn_v_RdL0_SplitSectionName(g_hGeometricInFile[i]->sName, sFile, sAction, sIdent);
      MLT_vSplitModuleSectionName(sIdent, sForme, sHabillage, &lNoPhy, &lNoLod, sName);
      
      // check form and mapping
	  if ((stricmp(sForme, sForme2) == 0) && (stricmp(sHabillage, sHabillage2) == 0)) 
      {
        *h_stObj = (MLT_tdstGeometricObject**)realloc(*h_stObj,((*p_lNbObj)+1)*sizeof(MLT_tdstGeometricObject*));
        (*h_stObj)[*p_lNbObj]=g_hGeometricInFile[i];
        (*p_lNbObj)++;
      }
    }
  }
}

/****************************************************************************
*		Description:	free all the objects in the library
*
*		Parameters:		
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vEraseLib()
{
  int i;

  if (g_hGeometricInFile == NULL) 
	  return;

  for (i=0; i<g_lGeometricIndex; i++)
  {
    if (g_hGeometricInFile[i] == NULL) 
		continue;
    MLT_xEraseGeometric(g_hGeometricInFile[i]);
  }

  g_lGeometricIndex = 0;
  free(g_hGeometricInFile);
  g_hGeometricInFile = NULL;
}


/****************************************************************************
*		Description:	free object in list
*
*		Parameters:		p_stObj		: object to erase
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vEraseObjInLib(MLT_tdstGeometricObject *p_stObj)
{
  int i;

  for (i=0; i<g_lGeometricIndex; i++)
  {
    if (g_hGeometricInFile[i] == p_stObj)
    {
      MLT_xEraseGeometric(g_hGeometricInFile[i]);
      g_hGeometricInFile[i] = NULL;
      break;
    }
  }
}


/****************************************************************************
*		Description:	mark object as not for save
*
*		Parameters:		p_stObj		: object to mark
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vEraseMergeObjInLib(MLT_tdstGeometricObject *p_stObj)
{
  p_stObj->bNotForSave = TRUE;
}


/****************************************************************************
*		Description:	free the specified Geometric Object
*
*		Parameters:		p_stGeometric : object to free
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_xEraseGeometric(MLT_tdstGeometricObject *p_stGeometric)
{
  // free all points
  if ((strlen(p_stGeometric->sPointsOf) == 0) && (p_stGeometric->xNbPoints != 0))
  {
    free(p_stGeometric->d_stListOfPoints);
    free(p_stGeometric->d_stListOfPointsNormals);
    free(p_stGeometric->d_stListOfPointsReceivedLightIntensity);
  }

  // free all edges
  if(p_stGeometric->xNbEdges != 0)
  {
    free(p_stGeometric->d_stListOfEdges);
  }

  // free all elements
  if ((!p_stGeometric->bNotForSave) && (p_stGeometric->xNbElements != 0))
  {
    int		i;
    long	lTest = 0;

    free(p_stGeometric->sElementOf);
    free(p_stGeometric->sIndexOf);

    for (i=0; i<p_stGeometric->xNbElements; i++)
      lTest += MLT_lEraseElementType(p_stGeometric->d_stListOfElements[i],
                            p_stGeometric->d_xListOfElementsTypes[i]);

    free(p_stGeometric->d_xListOfElementsTypes);
    if (lTest != p_stGeometric->xNbElements)
      free(p_stGeometric->d_stListOfElements);
  }

  // free structure
  free(p_stGeometric);
  return; 
}                      


/****************************************************************************
*		Description:	free the specified element in Geometric Object
*
*		Parameters:		p_vElement		: element to free
*						lElementType	: type of element
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
long MLT_lEraseElementType (void *p_vElement, long lElementType)
{
  if (p_vElement == NULL) 
	  return 0;

  switch(lElementType)
  {
    // free indexed triangle
    case MLT_C_xElementIndexedTriangles:
      {
        MLT_tdstElementIndexedTriangles *p_vLocal;

        p_vLocal = (MLT_tdstElementIndexedTriangles*)p_vElement;

		if (!strcmp(p_vLocal->sName, "")) 
			return -1;
		
		if (p_vLocal->d_stListOfFacesTripled) 
			free(p_vLocal->d_stListOfFacesTripled);
		if (p_vLocal->d_stListOfFacesTripledIndexUV)
			free(p_vLocal->d_stListOfFacesTripledIndexUV);
		if (p_vLocal->d_stListOfFacesNormals)
			free(p_vLocal->d_stListOfFacesNormals);
		if (p_vLocal->d_stListOfFacesReceivedLightIntensity)
			free(p_vLocal->d_stListOfFacesReceivedLightIntensity);
		if (p_vLocal->d_stListOfElementUV)
			free(p_vLocal->d_stListOfElementUV);
      }
      break;
    
	
	// free face map descriptor
	case MLT_C_xElementFaceMapDescriptors:
      {
        MLT_tdstElementFaceMapDescriptors *p_vLocal;

        p_vLocal = (MLT_tdstElementFaceMapDescriptors*)p_vElement;
      }
      break;
    
	// free sprite
	case MLT_C_xElementSprites:
      {
        MLT_tdstElementSprite *p_vLocal;
      
        p_vLocal = (MLT_tdstElementSprite*)p_vElement;
      }
      break;
    
	// free mesh
    case MLT_C_xElementTMeshes:
      {
        MLT_tdstElementTMeshes *p_vLocal;

        p_vLocal = (MLT_tdstElementTMeshes*)p_vElement;
      }
      break;
    
	// free point
    case MLT_C_xElementPoints:
      {
        MLT_tdstElementPoints *p_vLocal;

        p_vLocal = (MLT_tdstElementPoints*)p_vElement;
      }
      break;
    
	// free line
    case MLT_C_xElementLines:
      {
        MLT_tdstElementLines *p_vLocal;

        p_vLocal = (MLT_tdstElementLines*)p_vElement;
      }
      break;
    
	// free sphere
    case MLT_C_xElementSpheres:
      {
        MLT_tdstElementSpheres *p_vLocal;

        p_vLocal = (MLT_tdstElementSpheres*)p_vElement;
      }
      break;
    
	// free box
    case MLT_C_xElementAlignedBoxes:
      {
        MLT_tdstElementAlignedBoxes *p_vLocal;

        p_vLocal = (MLT_tdstElementAlignedBoxes*)p_vElement;
      }
      break;
    
	// free cone
    case MLT_C_xElementCones:
      {
        MLT_tdstElementCones *p_vLocal;

        p_vLocal = (MLT_tdstElementCones*)p_vElement;
      }
      break;

    // free mega face
    case MLT_C_xElementMegaFace:
      {
        MLT_tdstElementMegaFace *p_vLocal;

        p_vLocal = (MLT_tdstElementMegaFace*)p_vElement;

		if (!strcmp(p_vLocal->sName, "")) 
			return -1;
		
		if (p_vLocal->d_stListOfMegaFaces) 
			free(p_vLocal->d_stListOfMegaFaces);
      }
      break;

    case -1:
      return 1;
  }

  // free element
  free(p_vElement);
}


/****************************************************************************
*		Description:	merge two objects
*
*		Parameters:		p_stObj		: first object
*						p_stObjDup	: second object
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vMergeObjects (MLT_tdstGeometricObject *p_stObj, MLT_tdstGeometricObject *p_stObjDup)
{
  long i,j,k, lNbPoints, lNbEdges, lNbElements;

  // update saving flag
  p_stObj->bNotForSave = FALSE;

  // compute total number of points, edges and elements
  lNbPoints = p_stObj->xNbPoints + p_stObjDup->xNbPoints;
  lNbEdges = p_stObj->xNbEdges + p_stObjDup->xNbEdges;
  lNbElements = p_stObj->xNbElements + p_stObjDup->xNbElements;

  if( lNbPoints != 0)
  {
    // realloc points
	sprintf(p_stObj->sPointsOf, "");
    p_stObj->d_stListOfPoints=(MTH3D_tdstVector*)realloc(p_stObj->d_stListOfPoints, lNbPoints*sizeof(MTH3D_tdstVector));
    if (p_stObj->d_stListOfPoints==NULL)
      return;

    // realloc normals
    p_stObj->d_stListOfPointsNormals=(MTH3D_tdstVector*)realloc(p_stObj->d_stListOfPointsNormals, lNbPoints*sizeof(MTH3D_tdstVector));
    if (p_stObj->d_stListOfPointsNormals==NULL)
      return;

    // realloc RLI
    p_stObj->d_stListOfPointsReceivedLightIntensity=(MLT_tdstColor*)realloc(p_stObj->d_stListOfPointsReceivedLightIntensity, lNbPoints*sizeof(MLT_tdstColor));
    if (p_stObj->d_stListOfPointsReceivedLightIntensity==NULL)
      return;
  }

  if( lNbEdges != 0)
  {
    // realloc edges
    p_stObj->d_stListOfEdges=(MLT_tdstDoubledIndex*)realloc(p_stObj->d_stListOfEdges, lNbEdges*sizeof(MLT_tdstDoubledIndex));
    if (p_stObj->d_stListOfEdges==NULL)
      return;
  }

  if( lNbElements != 0)
  {
    // realloc element types
    p_stObj->d_xListOfElementsTypes=(long*)realloc(p_stObj->d_xListOfElementsTypes, lNbElements*sizeof(long));
    if (p_stObj->d_xListOfElementsTypes==NULL)
      return;

    // realloc elements
    p_stObj->d_stListOfElements=(void**)realloc(p_stObj->d_stListOfElements, lNbElements*sizeof(void*));
    if (p_stObj->d_stListOfElements==NULL)
      return;
  }

  // add all points from the second object
  for(j=0,i=p_stObj->xNbPoints; i<lNbPoints; j++,i++)
  {
    p_stObj->d_stListOfPoints[i].xX = p_stObjDup->d_stListOfPoints[j].xX;
    p_stObj->d_stListOfPoints[i].xY = p_stObjDup->d_stListOfPoints[j].xY;
    p_stObj->d_stListOfPoints[i].xZ = p_stObjDup->d_stListOfPoints[j].xZ;

    p_stObj->d_stListOfPointsNormals[i].xX = p_stObjDup->d_stListOfPointsNormals[j].xX;
    p_stObj->d_stListOfPointsNormals[i].xY = p_stObjDup->d_stListOfPointsNormals[j].xY;
    p_stObj->d_stListOfPointsNormals[i].xZ = p_stObjDup->d_stListOfPointsNormals[j].xZ;

    p_stObj->d_stListOfPointsReceivedLightIntensity[i].xR = p_stObjDup->d_stListOfPointsReceivedLightIntensity[j].xR;
    p_stObj->d_stListOfPointsReceivedLightIntensity[i].xG = p_stObjDup->d_stListOfPointsReceivedLightIntensity[j].xG;
    p_stObj->d_stListOfPointsReceivedLightIntensity[i].xB = p_stObjDup->d_stListOfPointsReceivedLightIntensity[j].xB;
  }

  // add all edges from the second object
  for(j=0,i=p_stObj->xNbEdges; i<lNbEdges; j++,i++)
  {
    p_stObj->d_stListOfEdges[i].a2_xIndex[0] = p_stObjDup->d_stListOfEdges[j].a2_xIndex[0]+p_stObj->xNbPoints;
    p_stObj->d_stListOfEdges[i].a2_xIndex[1] = p_stObjDup->d_stListOfEdges[j].a2_xIndex[1]+p_stObj->xNbPoints;
  }

  // add all elements from the second object
  for(j=0,i=p_stObj->xNbElements; i<lNbElements; j++,i++)
  {
    p_stObj->d_xListOfElementsTypes[i] = p_stObjDup->d_xListOfElementsTypes[j];

    switch(p_stObj->d_xListOfElementsTypes[i])
    {
      // copy indexed triangle
      case MLT_C_xElementIndexedTriangles:
		{
          MLT_tdstElementIndexedTriangles *p_vLocal, *p_vGlobal;
          long l;

          // create element
		  p_vLocal = (MLT_tdstElementIndexedTriangles*)malloc(sizeof(MLT_tdstElementIndexedTriangles));
		  p_stObj->d_stListOfElements[i] = p_vLocal;
		  p_vGlobal = (MLT_tdstElementIndexedTriangles*)p_stObjDup->d_stListOfElements[j];

		  // copy names
		  sprintf(p_vLocal->sName, "%s", p_vGlobal->sName);
		  sprintf(p_vLocal->sMaterial, "%s", p_vGlobal->sMaterial);

		  // copy material
		  p_vLocal->hMaterial = (MLT_tdstMaterial*)malloc(sizeof(MLT_tdstMaterial));
          
		  for(l=0;l<p_vGlobal->hMaterial->lTexture;l++)
			  sprintf(p_vLocal->hMaterial->sTexture[l], "%s", p_vGlobal->hMaterial->sTexture[l]);

		  p_vLocal->hMaterial->lTexture = p_vGlobal->hMaterial->lTexture;
		  sprintf(p_vLocal->hMaterial->sName, "%s", p_vGlobal->hMaterial->sName);
		  sprintf(p_vLocal->hMaterial->sMaterialType, "%s", p_vGlobal->hMaterial->sMaterialType);
		  p_vLocal->hMaterial->stAmbient = p_vGlobal->hMaterial->stAmbient;
		  p_vLocal->hMaterial->stDiffuse = p_vGlobal->hMaterial->stDiffuse;
		  p_vLocal->hMaterial->stSpecular = p_vGlobal->hMaterial->stSpecular;
		  p_vLocal->hMaterial->lSpecularExponent = p_vGlobal->hMaterial->lSpecularExponent;
		  p_vLocal->hMaterial->bAlreadySave = FALSE;

		  // copy sector
		  sprintf(p_vLocal->sSectorName, "%s", p_vGlobal->sSectorName);
		  
		  // copy parameters
		  p_vLocal->xNbFaces = p_vGlobal->xNbFaces;
		  p_vLocal->xNbElementUV = p_vGlobal->xNbElementUV;

		  // allocate faces
		  sprintf(p_vLocal->sFacesOf, "");
		  sprintf(p_vLocal->sUVsOf, "");
		  p_vLocal->d_stListOfFacesTripled = (MLT_tdstTripledIndex*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstTripledIndex));
		  p_vLocal->d_stListOfFacesNormals = (MTH3D_tdstVector*)malloc(p_vLocal->xNbFaces*sizeof(MTH3D_tdstVector));
		  p_vLocal->d_stListOfFacesTripledIndexUV = (MLT_tdstTripledIndex*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstTripledIndex));
		  p_vLocal->d_stListOfFacesReceivedLightIntensity = (MLT_tdstColor*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstColor));
		  p_vLocal->d_stListOfElementUV = (ACP_tdst2DUVValues*)malloc(p_vLocal->xNbElementUV*sizeof(ACP_tdst2DUVValues));

		  // copy elements
		  for(k=0; k<p_vLocal->xNbElementUV; k++)
		  {
			  p_vLocal->d_stListOfElementUV[k].xU = p_vGlobal->d_stListOfElementUV[k].xU;
			  p_vLocal->d_stListOfElementUV[k].xV = p_vGlobal->d_stListOfElementUV[k].xV;
		  }

		  // copy faces
		  for(k=0; k<p_vLocal->xNbFaces; k++)
		  {
			  p_vLocal->d_stListOfFacesTripled[k].a3_xIndex[0] = p_stObj->xNbPoints + p_vGlobal->d_stListOfFacesTripled[k].a3_xIndex[0];
			  p_vLocal->d_stListOfFacesTripled[k].a3_xIndex[1] = p_stObj->xNbPoints + p_vGlobal->d_stListOfFacesTripled[k].a3_xIndex[1];
			  p_vLocal->d_stListOfFacesTripled[k].a3_xIndex[2] = p_stObj->xNbPoints + p_vGlobal->d_stListOfFacesTripled[k].a3_xIndex[2];

			  p_vLocal->d_stListOfFacesTripledIndexUV[k].a3_xIndex[0] = p_vGlobal->d_stListOfFacesTripledIndexUV[k].a3_xIndex[1];
			  p_vLocal->d_stListOfFacesTripledIndexUV[k].a3_xIndex[1] = p_vGlobal->d_stListOfFacesTripledIndexUV[k].a3_xIndex[0];
			  p_vLocal->d_stListOfFacesTripledIndexUV[k].a3_xIndex[2] = p_vGlobal->d_stListOfFacesTripledIndexUV[k].a3_xIndex[2];

			  p_vLocal->d_stListOfFacesNormals[k].xX = - p_vGlobal->d_stListOfFacesNormals[k].xX;
			  p_vLocal->d_stListOfFacesNormals[k].xY = - p_vGlobal->d_stListOfFacesNormals[k].xY;
			  p_vLocal->d_stListOfFacesNormals[k].xZ = - p_vGlobal->d_stListOfFacesNormals[k].xZ;

			  p_vLocal->d_stListOfFacesReceivedLightIntensity[k].xR = p_vGlobal->d_stListOfFacesReceivedLightIntensity[k].xR;
			  p_vLocal->d_stListOfFacesReceivedLightIntensity[k].xG = p_vGlobal->d_stListOfFacesReceivedLightIntensity[k].xG;
			  p_vLocal->d_stListOfFacesReceivedLightIntensity[k].xB = p_vGlobal->d_stListOfFacesReceivedLightIntensity[k].xB;
		  }
		}
        break;

		
      // copy face map descriptor
	  case MLT_C_xElementFaceMapDescriptors:
        {
          MLT_tdstElementFaceMapDescriptors *p_vLocal, *p_vGlobal;
          long l;

          // create element
          p_vLocal = (MLT_tdstElementFaceMapDescriptors*)malloc(sizeof(MLT_tdstElementFaceMapDescriptors));
          p_stObj->d_stListOfElements[i] = p_vLocal;
          p_vGlobal = (MLT_tdstElementFaceMapDescriptors*)p_stObjDup->d_stListOfElements[j];

		  // copy names
          sprintf(p_vLocal->sName, "%s", p_vGlobal->sName);
          p_vLocal->xNbFaces = p_vGlobal->xNbFaces;

          // allocate faces
		  p_vLocal->d_stListOfFacesQuadrupled = (MLT_tdstFaceMapTriangle*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstFaceMapTriangle));
          p_vLocal->d_stListOfFacesNormals = (MTH3D_tdstVector*)malloc(p_vLocal->xNbFaces*sizeof(MTH3D_tdstVector));

          // copy faces
		  for(k=0; k<p_vLocal->xNbFaces; k++)
          {
            MLT_tdstFaceMapDescriptor *p_hFmdLoc, *p_hFmdGlo;

            p_vLocal->d_stListOfFacesQuadrupled[k].stFaceTripled.a3_xIndex[0] = p_stObj->xNbPoints + p_vGlobal->d_stListOfFacesQuadrupled[k].stFaceTripled.a3_xIndex[0];
            p_vLocal->d_stListOfFacesQuadrupled[k].stFaceTripled.a3_xIndex[1] = p_stObj->xNbPoints + p_vGlobal->d_stListOfFacesQuadrupled[k].stFaceTripled.a3_xIndex[2];
            p_vLocal->d_stListOfFacesQuadrupled[k].stFaceTripled.a3_xIndex[2] = p_stObj->xNbPoints + p_vGlobal->d_stListOfFacesQuadrupled[k].stFaceTripled.a3_xIndex[1];
            
            p_hFmdLoc = (MLT_tdstFaceMapDescriptor *)malloc(sizeof(MLT_tdstFaceMapDescriptor));
            p_hFmdGlo = p_vGlobal->d_stListOfFacesQuadrupled[k].hFaceMapDescriptor;
            p_vLocal->d_stListOfFacesQuadrupled[k].hFaceMapDescriptor = p_hFmdLoc;
            p_hFmdLoc->AlreadySave = TRUE;
            sprintf(p_hFmdLoc->sName, "%s", p_hFmdGlo->sName);;
            p_hFmdLoc->stUVValues[0].xU = p_hFmdGlo->stUVValues[0].xU;
            p_hFmdLoc->stUVValues[0].xV = p_hFmdGlo->stUVValues[0].xV;
            p_hFmdLoc->stUVValues[1].xU = p_hFmdGlo->stUVValues[0].xU;
            p_hFmdLoc->stUVValues[1].xV = p_hFmdGlo->stUVValues[0].xV;
            p_hFmdLoc->stUVValues[2].xU = p_hFmdGlo->stUVValues[0].xU;
            p_hFmdLoc->stUVValues[2].xV = p_hFmdGlo->stUVValues[0].xV;
            sprintf(p_hFmdLoc->sMaterial, "%s", p_hFmdGlo->sMaterial);
            sprintf(p_hFmdLoc->sMaterialFile, "%s", p_hFmdGlo->sMaterialFile);
            sprintf(p_hFmdLoc->sSprObjName, "%s", p_hFmdGlo->sSprObjName);
            sprintf(p_hFmdLoc->sSprObjFile, "%s", p_hFmdGlo->sSprObjFile);

            p_hFmdLoc->hMaterial = (MLT_tdstMaterial*)malloc(sizeof(MLT_tdstMaterial));
            sprintf(p_hFmdLoc->hMaterial->sName, "%s", p_hFmdGlo->hMaterial->sName);
            
            for(l=0;l<p_hFmdGlo->hMaterial->lTexture;l++)
              sprintf(p_hFmdLoc->hMaterial->sTexture[l], "%s", p_hFmdGlo->hMaterial->sTexture[l]);

            p_hFmdLoc->hMaterial->lTexture = p_hFmdGlo->hMaterial->lTexture;
            sprintf(p_hFmdLoc->hMaterial->sMaterialType, "%s", p_hFmdGlo->hMaterial->sMaterialType);
            p_hFmdLoc->hMaterial->stAmbient = p_hFmdGlo->hMaterial->stAmbient;
            p_hFmdLoc->hMaterial->stDiffuse = p_hFmdGlo->hMaterial->stDiffuse;
            p_hFmdLoc->hMaterial->stSpecular = p_hFmdGlo->hMaterial->stSpecular;
            p_hFmdLoc->hMaterial->lSpecularExponent = p_hFmdGlo->hMaterial->lSpecularExponent;
            p_hFmdLoc->hMaterial->bAlreadySave = TRUE;

            p_vLocal->d_stListOfFacesNormals[k].xX = - p_vGlobal->d_stListOfFacesNormals[k].xX;
            p_vLocal->d_stListOfFacesNormals[k].xY = - p_vGlobal->d_stListOfFacesNormals[k].xY;
            p_vLocal->d_stListOfFacesNormals[k].xZ = - p_vGlobal->d_stListOfFacesNormals[k].xZ;

            p_vLocal->d_stListOfFacesReceivedLightIntensity[k].xR = p_vGlobal->d_stListOfFacesReceivedLightIntensity[k].xR;
            p_vLocal->d_stListOfFacesReceivedLightIntensity[k].xG = p_vGlobal->d_stListOfFacesReceivedLightIntensity[k].xG;
            p_vLocal->d_stListOfFacesReceivedLightIntensity[k].xB = p_vGlobal->d_stListOfFacesReceivedLightIntensity[k].xB;
          }
        }
        break;
    }
  }

  // update object
  p_stObj->xNbElements = lNbElements;
  p_stObj->xNbEdges = lNbEdges;
  p_stObj->xNbPoints = lNbPoints;
}


/****************************************************************************
*		Description:	make object with inverse faces normals
*
*		Parameters:		p_stObj		: source object
*						h_stObjRev	: result reversed object
*						sSector		: sector name
*---------------------------------------------------------------------------
*		Revision date:                                      Author:         
*****************************************************************************/
void MLT_vMakeReverseObjInLib (MLT_tdstGeometricObject *p_stObj, MLT_tdstGeometricObject **h_stObjRev, char *sSector)
{
  long		i;
  static	name = 0;
  xString	sIdent, sFile;

  // alloc reversed object
  *h_stObjRev = (MLT_tdstGeometricObject *)malloc(sizeof(MLT_tdstGeometricObject));

  // add it in library
  g_hGeometricInFile = (MLT_tdstGeometricObject**)realloc(g_hGeometricInFile,(g_lGeometricIndex+1)*sizeof(MLT_tdstGeometricObject*));
  g_hGeometricInFile[g_lGeometricIndex] = (*h_stObjRev);
  g_lGeometricIndex++;

  // init string parameters
  sprintf(sIdent, "%s_%s", M_NameGothrough, sSector);
  sprintf(sFile, "%s.mod", g_sFileIn);
  sprintf((*h_stObjRev)->sPointsOf, "");
  sprintf((*h_stObjRev)->sComment, p_stObj->sComment);
  SCR_fn_v_RdL0_ComputeSectionName((*h_stObjRev)->sName, sFile, M_Geometric, sIdent);
  // init flags and indexes
  (*h_stObjRev)->bNotForSave = FALSE;
  (*h_stObjRev)->xNbPoints = p_stObj->xNbPoints;
  (*h_stObjRev)->xNbElements = p_stObj->xNbElements;
  (*h_stObjRev)->xNbEdges = p_stObj->xNbEdges;
  
  // allocate lists
  (*h_stObjRev)->d_stListOfPoints=(MTH3D_tdstVector*)malloc(p_stObj->xNbPoints*sizeof(MTH3D_tdstVector));
  (*h_stObjRev)->d_stListOfPointsNormals=(MTH3D_tdstVector*)malloc(p_stObj->xNbPoints*sizeof(MTH3D_tdstVector));
  (*h_stObjRev)->d_stListOfPointsReceivedLightIntensity=(MLT_tdstColor*)malloc(p_stObj->xNbPoints*sizeof(MLT_tdstColor));
  (*h_stObjRev)->d_stListOfEdges=(MLT_tdstDoubledIndex*)malloc(p_stObj->xNbEdges*sizeof(MLT_tdstDoubledIndex));
  (*h_stObjRev)->d_xListOfElementsTypes=(long*)malloc(p_stObj->xNbElements*sizeof(long));
  (*h_stObjRev)->d_stListOfElements=(void**)malloc(p_stObj->xNbElements*sizeof(void*));

  // copy all points
  for (i=0; i<p_stObj->xNbPoints; i++)
  {
    sprintf((*h_stObjRev)->sPointsOf, "");
    (*h_stObjRev)->d_stListOfPoints[i].xX=p_stObj->d_stListOfPoints[i].xX;
    (*h_stObjRev)->d_stListOfPoints[i].xY=p_stObj->d_stListOfPoints[i].xY;
    (*h_stObjRev)->d_stListOfPoints[i].xZ=p_stObj->d_stListOfPoints[i].xZ;

    (*h_stObjRev)->d_stListOfPointsNormals[i].xX=p_stObj->d_stListOfPointsNormals[i].xX;
    (*h_stObjRev)->d_stListOfPointsNormals[i].xY=p_stObj->d_stListOfPointsNormals[i].xY;
    (*h_stObjRev)->d_stListOfPointsNormals[i].xZ=p_stObj->d_stListOfPointsNormals[i].xZ;

    (*h_stObjRev)->d_stListOfPointsReceivedLightIntensity[i].xR=p_stObj->d_stListOfPointsReceivedLightIntensity[i].xR;
    (*h_stObjRev)->d_stListOfPointsReceivedLightIntensity[i].xG=p_stObj->d_stListOfPointsReceivedLightIntensity[i].xG;
    (*h_stObjRev)->d_stListOfPointsReceivedLightIntensity[i].xB=p_stObj->d_stListOfPointsReceivedLightIntensity[i].xB;
  }

  // copy all edges
  for (i=0; i<p_stObj->xNbEdges; i++)
  {
    (*h_stObjRev)->d_stListOfEdges[i].a2_xIndex[0]=p_stObj->d_stListOfEdges[i].a2_xIndex[0];
    (*h_stObjRev)->d_stListOfEdges[i].a2_xIndex[1]=p_stObj->d_stListOfEdges[i].a2_xIndex[1];
  }

  // copy all elements
  for (i=0; i<p_stObj->xNbElements; i++)
  {
    (*h_stObjRev)->d_xListOfElementsTypes[i]=p_stObj->d_xListOfElementsTypes[i];

    // copy indexed triangle
	if (p_stObj->d_xListOfElementsTypes[i] == MLT_C_xElementIndexedTriangles)
    {
		MLT_tdstElementIndexedTriangles *p_vLocal, *p_vGlobal;
		long j;

		p_vLocal = (MLT_tdstElementIndexedTriangles*)malloc(sizeof(MLT_tdstElementIndexedTriangles));
		p_vGlobal = p_stObj->d_stListOfElements[i];
		(*h_stObjRev)->d_stListOfElements[i] = (void*)p_vLocal;

		sprintf(sIdent, "%s_%i", sSector, name++);
		sprintf(sFile, "%s.mod", g_sFileIn);
		SCR_fn_v_RdL0_ComputeSectionName(p_vLocal->sName, sFile, M_ElementIndexedTriangles, sIdent);
		sprintf(p_vLocal->sMaterial, "%s", p_vGlobal->sMaterial);

		p_vLocal->hMaterial = (MLT_tdstMaterial*)malloc(sizeof(MLT_tdstMaterial));
		sprintf(p_vLocal->hMaterial->sName, "%s", p_vGlobal->hMaterial->sName);

		for(j=0;j<p_vGlobal->hMaterial->lTexture;j++)
			sprintf(p_vLocal->hMaterial->sTexture[j], "%s", p_vGlobal->hMaterial->sTexture[j]);

		p_vLocal->hMaterial->lTexture = p_vGlobal->hMaterial->lTexture;
		sprintf(p_vLocal->hMaterial->sMaterialType, "%s", p_vGlobal->hMaterial->sMaterialType);
		p_vLocal->hMaterial->stAmbient = p_vGlobal->hMaterial->stAmbient;
		p_vLocal->hMaterial->stDiffuse = p_vGlobal->hMaterial->stDiffuse;
		p_vLocal->hMaterial->stSpecular = p_vGlobal->hMaterial->stSpecular;
		p_vLocal->hMaterial->lSpecularExponent = p_vGlobal->hMaterial->lSpecularExponent;
		p_vLocal->hMaterial->bAlreadySave = TRUE;
      
		sprintf(p_vLocal->sSectorName, "%s", p_vGlobal->sSectorName);
		p_vLocal->xNbFaces = p_vGlobal->xNbFaces;
		p_vLocal->xNbElementUV = p_vGlobal->xNbElementUV;

		sprintf(p_vLocal->sFacesOf, "");
		sprintf(p_vLocal->sUVsOf, "");
		p_vLocal->d_stListOfFacesTripled = (MLT_tdstTripledIndex*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstTripledIndex));
		p_vLocal->d_stListOfFacesNormals = (MTH3D_tdstVector*)malloc(p_vLocal->xNbFaces*sizeof(MTH3D_tdstVector));
		p_vLocal->d_stListOfFacesTripledIndexUV = (MLT_tdstTripledIndex*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstTripledIndex));
		p_vLocal->d_stListOfFacesReceivedLightIntensity = (MLT_tdstColor*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstColor));
		p_vLocal->d_stListOfElementUV = (ACP_tdst2DUVValues*)malloc(p_vLocal->xNbElementUV*sizeof(ACP_tdst2DUVValues));

		for(j=0; j<p_vLocal->xNbElementUV; j++)
		{
			p_vLocal->d_stListOfElementUV[j].xU = p_vGlobal->d_stListOfElementUV[j].xU;
			p_vLocal->d_stListOfElementUV[j].xV = p_vGlobal->d_stListOfElementUV[j].xV;
		}

		for(j=0; j<p_vLocal->xNbFaces; j++)
		{
			p_vLocal->d_stListOfFacesTripled[j].a3_xIndex[0] = p_vGlobal->d_stListOfFacesTripled[j].a3_xIndex[0];
			p_vLocal->d_stListOfFacesTripled[j].a3_xIndex[1] = p_vGlobal->d_stListOfFacesTripled[j].a3_xIndex[2];
			p_vLocal->d_stListOfFacesTripled[j].a3_xIndex[2] = p_vGlobal->d_stListOfFacesTripled[j].a3_xIndex[1];

			p_vLocal->d_stListOfFacesTripledIndexUV[j].a3_xIndex[0] = p_vGlobal->d_stListOfFacesTripledIndexUV[j].a3_xIndex[0];
			p_vLocal->d_stListOfFacesTripledIndexUV[j].a3_xIndex[1] = p_vGlobal->d_stListOfFacesTripledIndexUV[j].a3_xIndex[2];
			p_vLocal->d_stListOfFacesTripledIndexUV[j].a3_xIndex[2] = p_vGlobal->d_stListOfFacesTripledIndexUV[j].a3_xIndex[1];

			p_vLocal->d_stListOfFacesNormals[j].xX = - p_vGlobal->d_stListOfFacesNormals[j].xX;
			p_vLocal->d_stListOfFacesNormals[j].xY = - p_vGlobal->d_stListOfFacesNormals[j].xY;
			p_vLocal->d_stListOfFacesNormals[j].xZ = - p_vGlobal->d_stListOfFacesNormals[j].xZ;
  
			p_vLocal->d_stListOfFacesReceivedLightIntensity[j].xR = p_vGlobal->d_stListOfFacesReceivedLightIntensity[j].xR;
			p_vLocal->d_stListOfFacesReceivedLightIntensity[j].xG = p_vGlobal->d_stListOfFacesReceivedLightIntensity[j].xG;
			p_vLocal->d_stListOfFacesReceivedLightIntensity[j].xB = p_vGlobal->d_stListOfFacesReceivedLightIntensity[j].xB;
		}
    }
    // copy face map descriptor
	else if(p_stObj->d_xListOfElementsTypes[i] == MLT_C_xElementFaceMapDescriptors)
    {
      MLT_tdstElementFaceMapDescriptors *p_vLocal, *p_vGlobal;
      long j;

      p_vLocal = (MLT_tdstElementFaceMapDescriptors*)malloc(sizeof(MLT_tdstElementFaceMapDescriptors));
      p_vGlobal = p_stObj->d_stListOfElements[i];
      (*h_stObjRev)->d_stListOfElements[i] = (void*)p_vLocal;

      sprintf(p_vLocal->sName, "%s", p_vGlobal->sName);
      p_vLocal->xNbFaces = p_vGlobal->xNbFaces;

      p_vLocal->d_stListOfFacesQuadrupled = (MLT_tdstFaceMapTriangle*)malloc(p_vLocal->xNbFaces*sizeof(MLT_tdstFaceMapTriangle));
      p_vLocal->d_stListOfFacesNormals = (MTH3D_tdstVector*)malloc(p_vLocal->xNbFaces*sizeof(MTH3D_tdstVector));

      for(j=0; j<p_vLocal->xNbFaces; j++)
      {
        p_vLocal->d_stListOfFacesQuadrupled[j].stFaceTripled.a3_xIndex[0] = p_vGlobal->d_stListOfFacesQuadrupled[j].stFaceTripled.a3_xIndex[0];
        p_vLocal->d_stListOfFacesQuadrupled[j].stFaceTripled.a3_xIndex[1] = p_vGlobal->d_stListOfFacesQuadrupled[j].stFaceTripled.a3_xIndex[2];
        p_vLocal->d_stListOfFacesQuadrupled[j].stFaceTripled.a3_xIndex[2] = p_vGlobal->d_stListOfFacesQuadrupled[j].stFaceTripled.a3_xIndex[1];
      
        p_vLocal->d_stListOfFacesNormals[j].xX = - p_vGlobal->d_stListOfFacesNormals[j].xX;
        p_vLocal->d_stListOfFacesNormals[j].xY = - p_vGlobal->d_stListOfFacesNormals[j].xY;
        p_vLocal->d_stListOfFacesNormals[j].xZ = - p_vGlobal->d_stListOfFacesNormals[j].xZ;

        p_vLocal->d_stListOfFacesReceivedLightIntensity[i].xR = p_vGlobal->d_stListOfFacesReceivedLightIntensity[i].xR;
        p_vLocal->d_stListOfFacesReceivedLightIntensity[i].xG = p_vGlobal->d_stListOfFacesReceivedLightIntensity[i].xG;
        p_vLocal->d_stListOfFacesReceivedLightIntensity[i].xB = p_vGlobal->d_stListOfFacesReceivedLightIntensity[i].xB;
      }
    }
  }
}


