reman3/Rayman_X/cpa/Appli/Max23Dos/src/Merge.c

433 lines
16 KiB
C

/*=========================================================================
*
* Merge.c - merge functions
*
* Version 1.0
* Revision date
*
*=======================================================================*/
#include "Merge.h"
#include "print.h"
#include "ModLib.h"
#include "ModLoad.h"
//--- Macros ---------------------------------------------------------
#define MLT_M_xEpsilon 1e-3
#define MLT_M_bVectorEqualWithEpsilon( _p_stVect1_, _p_stVect2_)\
(\
( MTH_M_bEqualWithEpsilon((_p_stVect1_)->xX, (_p_stVect2_)->xX, MLT_M_xEpsilon ))\
&& ( MTH_M_bEqualWithEpsilon((_p_stVect1_)->xY, (_p_stVect2_)->xY, MLT_M_xEpsilon ))\
&& ( MTH_M_bEqualWithEpsilon((_p_stVect1_)->xZ, (_p_stVect2_)->xZ, MLT_M_xEpsilon ))\
)
//--- Global statics ---------------------------------------------------------
static char gs_szMergedName[ SCR_CV_ui_Cfg_MaxLenName ];
//--------------------------------------------------------------------
/****************************************************************************
* Description: merge super object child if needed (recursive function)
*
* Parameters: _hSO : SuperObject to treat
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
void MLT_vMergeObjectsInHierarchy ( MLT_tdxHandleToSuperObject _hSO )
{
MLT_tdxHandleToSuperObject *hCurrentChild, *hLastChild, *hSecondChild, *hThirdChild;
long lGroupIndex;
tdstMergeData *p_stMergeData;
// init pointers
hCurrentChild = _hSO->d_hChild;
hLastChild = hCurrentChild + _hSO->lNbChild;
for (; hCurrentChild < hLastChild; hCurrentChild++)
{
// check if this is an element
lGroupIndex = MLT_lMergeGetIndexAndName( (*hCurrentChild)->sName, gs_szMergedName);
if ( lGroupIndex != -1 )
{
// create data and search for all item in group
p_stMergeData = MLT_pstMergeDataCreate( gs_szMergedName, _hSO->lNbChild );
MLT_vMergeDataAddSO( p_stMergeData, *hCurrentChild, lGroupIndex );
for( hSecondChild = hCurrentChild + 1; hSecondChild < hLastChild; hSecondChild++)
{
lGroupIndex = MLT_lMergeGetIndexAndName( (*hSecondChild)->sName, gs_szMergedName);
if ( (lGroupIndex != -1) && (stricmp( gs_szMergedName, p_stMergeData->szSOName) == 0) )
MLT_vMergeDataAddSO( p_stMergeData, *hSecondChild, lGroupIndex );
}
// Merge geometric object
MLT_vComputeNewGeometric( p_stMergeData );
// update super object (flags and SPOFlags must not be erased !)
strcpy(_hSO->sName, p_stMergeData->szSOName);
lGroupIndex = MLT_lMergeGetIndexAndName( (*hCurrentChild)->p_stMatrix->sName, gs_szMergedName);
strcpy(_hSO->p_stMatrix->sName, gs_szMergedName);
strcpy(_hSO->sGeometric, p_stMergeData->szObjName);
// update hierarchy
hSecondChild = hThirdChild = hCurrentChild;
for( ; hSecondChild < hLastChild; hSecondChild++)
{
lGroupIndex = MLT_lMergeDataGetSOIndex( p_stMergeData, *hSecondChild );
if (lGroupIndex == -1)
*hThirdChild++ = *hSecondChild;
}
// update children of super-object
_hSO->lNbChild -= p_stMergeData->lNumberOfSO;
hLastChild -= p_stMergeData->lNumberOfSO;
//free merge data
MLT_vMergeDataFree( p_stMergeData );
}
// test next level
else
MLT_vMergeObjectsInHierarchy(*hCurrentChild);
}
}
/****************************************************************************
* Description: merge geometric object associated with the SO to be merged
*
* Parameters: _p_stMergeData : merge data initialized with list of SO to merge
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
void MLT_vComputeNewGeometric ( tdstMergeData *_p_stMergeData )
{
long lIndex;
long lGroupIndex;
MLT_tdstGeometricObject *p_stObj;
// allocate memory to store geometric pointer
_p_stMergeData->d_p_stObject = (MLT_tdstGeometricObject **) malloc( sizeof(MLT_tdstGeometricObject *) * _p_stMergeData->lNumberOfSO);
// get all geometric object to store
for ( lIndex = 0; lIndex < _p_stMergeData->lNumberOfSO; lIndex++ )
{
_p_stMergeData->d_p_stObject[lIndex] = p_stObj = MLT_pFindInLib( _p_stMergeData->d_hSO[lIndex]->sGeometric );
if(p_stObj == NULL)
{
MLT_vOutput( C_ComRes_cErrorLine, "\nError : Can't load %s", _p_stMergeData->d_hSO[lIndex]->sGeometric);
return;
}
if (lIndex == 0)
lGroupIndex = MLT_lMergeGetIndexAndName( p_stObj->sName, _p_stMergeData->szObjName );
else
p_stObj->bNotForSave = TRUE;
}
// merge all elements
_p_stMergeData->p_stMergedObject = p_stObj = (MLT_tdstGeometricObject *) malloc( sizeof(MLT_tdstGeometricObject) );
memset( p_stObj, 0, sizeof(MLT_tdstGeometricObject) );
strcpy( p_stObj->sName, _p_stMergeData->szObjName );
// count number of point, element, vertex, ...
for (lIndex = 0; lIndex < _p_stMergeData->lNumberOfSO; lIndex++ )
{
p_stObj->lNbLod = _p_stMergeData->d_p_stObject[lIndex]->lNbLod;
p_stObj->xNbPoints += _p_stMergeData->d_p_stObject[lIndex]->xNbPoints;
p_stObj->xNbElements += _p_stMergeData->d_p_stObject[lIndex]->xNbElements;
p_stObj->xNbEdges += _p_stMergeData->d_p_stObject[lIndex]->xNbEdges;
}
// allocate new object
MLT_xAllocateGeometric( p_stObj );
// merge geometric data
MLT_vMergeGeometric( _p_stMergeData );
// put new object in lib, in place of old one
memcpy( _p_stMergeData->d_p_stObject[0], _p_stMergeData->p_stMergedObject, sizeof(MLT_tdstGeometricObject) );
}
/****************************************************************************
* Description: merge geometric element into result geometric object
*
* Parameters: _p_stMergeData : merge data initialized with list of SO Object and allocated result object
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
void MLT_vMergeGeometric ( tdstMergeData *_p_stMergeData )
{
long lIndex;
MLT_tdstGeometricObject *p_stObj;
MLT_tdstGeometricObject *p_stCurObj;
long *d_lIndex, *p_stCurIndex;
long **d_p_lObjFirstVert;
MTH3D_tdstVector stTranslation;
MTH3D_tdstVector *p_stCurrentVertex, *p_stVertex, *p_stLastVertex;
MTH3D_tdstVector *p_stSearchVertex, *p_stLastSearchVertex;
long *p_lCurElementType;
void **pp_vCurElement, **pp_vLastElem, **pp_vSearchElement;
MLT_tdstElementIndexedTriangles *p_stETIT;
MLT_tdstElementSprite *p_stESt;
MLT_tdstTripledIndex *p_stFace, *p_stLastFace;
MLT_tdstIndexedSprite *p_stSprite, *p_stLastSprite;
// allocate array for vertices index correspondance
p_stObj = _p_stMergeData->p_stMergedObject;
d_lIndex = (long *) calloc( p_stObj->xNbPoints, sizeof(long) );
d_p_lObjFirstVert = (long **) malloc (_p_stMergeData->lNumberOfSO * sizeof(long *) );
// copy all points of first object
p_stCurObj = _p_stMergeData->d_p_stObject[0];
memcpy( p_stObj->d_stListOfPoints, p_stCurObj->d_stListOfPoints, p_stCurObj->xNbPoints * sizeof( MTH3D_tdstVector ) );
memcpy( p_stObj->d_stListOfPointsNormals, p_stCurObj->d_stListOfPointsNormals, p_stCurObj->xNbPoints * sizeof( MTH3D_tdstVector ) );
memcpy( p_stObj->d_stListOfPointsReceivedLightIntensity, p_stCurObj->d_stListOfPointsReceivedLightIntensity, p_stCurObj->xNbPoints * sizeof( MLT_tdstColor ) );
d_p_lObjFirstVert[0] = d_lIndex;
p_stCurrentVertex = p_stObj->d_stListOfPoints + p_stCurObj->xNbPoints;
// now copy all points of others object
for ( lIndex = 1; lIndex < _p_stMergeData->lNumberOfSO; lIndex++)
{
MTH3D_M_vSubVector( &stTranslation, &_p_stMergeData->d_hSO[lIndex]->p_stMatrix->stTranslation, &_p_stMergeData->stOrigin );
d_p_lObjFirstVert[ lIndex ] = d_p_lObjFirstVert[ lIndex - 1 ] + p_stCurObj->xNbPoints;
p_stCurObj = _p_stMergeData->d_p_stObject[ lIndex ];
p_stVertex = p_stCurObj->d_stListOfPoints;
p_stLastVertex = p_stVertex + p_stCurObj->xNbPoints;
p_stCurIndex = d_p_lObjFirstVert[ lIndex ];
p_stLastSearchVertex = p_stCurrentVertex;
for ( ; p_stVertex < p_stLastVertex; p_stVertex++, p_stCurIndex++)
{
MTH3D_M_vAddVector( p_stVertex, p_stVertex, &stTranslation );
// search in all previous point for a equal point
for (p_stSearchVertex = p_stObj->d_stListOfPoints; p_stSearchVertex < p_stLastSearchVertex; p_stSearchVertex++)
{
if( MLT_M_bVectorEqualWithEpsilon( p_stVertex, p_stSearchVertex ) )
{
*p_stCurIndex = p_stSearchVertex - p_stObj->d_stListOfPoints;
break;
}
}
if (p_stSearchVertex == p_stLastSearchVertex)
{
MTH3D_M_vCopyVector( p_stCurrentVertex, p_stVertex );
*p_stCurIndex = p_stCurrentVertex++ - p_stObj->d_stListOfPoints;
}
}
}
// recompute number of points
p_stObj->xNbPoints = p_stCurrentVertex - p_stObj->d_stListOfPoints;
// copy first object element without change
p_stCurObj = _p_stMergeData->d_p_stObject[0];
p_lCurElementType = p_stObj->d_xListOfElementsTypes;
pp_vCurElement = p_stObj->d_stListOfElements;
memcpy( p_lCurElementType, p_stCurObj->d_xListOfElementsTypes, p_stCurObj->xNbElements * sizeof( long) );
memcpy( pp_vCurElement, p_stCurObj->d_stListOfElements, p_stCurObj->xNbElements * sizeof( long) );
p_lCurElementType += p_stCurObj->xNbElements;
pp_vCurElement += p_stCurObj->xNbElements;
// add others element with change to vertices point
for (lIndex = 1; lIndex < _p_stMergeData->lNumberOfSO; lIndex++)
{
p_stCurObj = _p_stMergeData->d_p_stObject[ lIndex ];
memcpy( p_lCurElementType, p_stCurObj->d_xListOfElementsTypes, p_stCurObj->xNbElements * sizeof( long) );
memcpy( pp_vCurElement, p_stCurObj->d_stListOfElements, p_stCurObj->xNbElements * sizeof( long) );
pp_vLastElem = pp_vCurElement + p_stCurObj->xNbElements;
for (; pp_vCurElement < pp_vLastElem; pp_vCurElement++, p_lCurElementType++)
{
switch( *p_lCurElementType )
{
case 1:
p_stETIT = (MLT_tdstElementIndexedTriangles *) *pp_vCurElement;
p_stFace = p_stETIT->d_stListOfFacesTripled;
p_stLastFace = p_stFace + p_stETIT->xNbFaces;
for ( ; p_stFace < p_stLastFace ; p_stFace++ )
{
p_stFace->a3_xIndex[0] = d_p_lObjFirstVert[lIndex][ p_stFace->a3_xIndex[0] ];
p_stFace->a3_xIndex[1] = d_p_lObjFirstVert[lIndex][ p_stFace->a3_xIndex[1] ];
p_stFace->a3_xIndex[2] = d_p_lObjFirstVert[lIndex][ p_stFace->a3_xIndex[2] ];
}
break;
case 3:
p_stESt = (MLT_tdstElementSprite *) pp_vCurElement;
p_stSprite = p_stESt->d_stListOfSprites;
p_stLastSprite = p_stSprite + p_stESt->xNbSprites;
for ( ; p_stSprite < p_stLastSprite ; p_stSprite++ )
{
p_stSprite->xCenterPoint = d_p_lObjFirstVert[lIndex][ p_stSprite->xCenterPoint ];
}
break;
}
}
}
// compute all element bounding box index and name
pp_vCurElement = p_stObj->d_stListOfElements;
pp_vLastElem = pp_vCurElement + p_stObj->xNbElements;
p_lCurElementType = p_stObj->d_xListOfElementsTypes;
for ( ; pp_vCurElement < pp_vLastElem; pp_vCurElement++, p_lCurElementType++ )
{
p_stETIT = (MLT_tdstElementIndexedTriangles *) *pp_vCurElement;
p_stETIT->xIndexOfParallelBox = (ACP_tdxIndex) MLT_lMergeGetIndexAndName( p_stETIT->sName, gs_szMergedName);
// look if element name is duplicate
pp_vSearchElement = p_stObj->d_stListOfElements;
for ( ; pp_vSearchElement < pp_vCurElement; pp_vSearchElement++ )
{
if (stricmp( gs_szMergedName, ((MLT_tdstElementIndexedTriangles *) (*pp_vSearchElement))->sName) == 0)
break;
}
if (pp_vSearchElement != pp_vCurElement)
sprintf( p_stETIT->sName, "%s%d", gs_szMergedName, p_stETIT->xIndexOfParallelBox );
else
strcpy( p_stETIT->sName, gs_szMergedName );
}
}
/****************************************************************************
* Description: create a merge data structure and allocate memory to store information
*
* Parameters: _szName : name of merged group
* _lNumberMax : number max of element in group
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
tdstMergeData *MLT_pstMergeDataCreate ( char *_szName, long _lNumberMax )
{
tdstMergeData *p_stMergeData;
p_stMergeData = (tdstMergeData *) malloc (sizeof( tdstMergeData ) );
strcpy( p_stMergeData->szSOName, _szName );
p_stMergeData->d_hSO = (MLT_tdxHandleToSuperObject *) malloc ( sizeof(MLT_tdxHandleToSuperObject) * _lNumberMax );
p_stMergeData->d_lIndex = (long *) malloc ( sizeof(long) * _lNumberMax );
p_stMergeData->lNumberOfSO = 0;
p_stMergeData->d_p_stObject = NULL;
return p_stMergeData;
}
/****************************************************************************
* Description: free merge data. (no parameters validity check )
*
* Parameters: p_stMergeData : merge data to deallocate
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
void MLT_vMergeDataFree ( tdstMergeData *_p_stMergeData )
{
free( _p_stMergeData->d_hSO );
free( _p_stMergeData->d_lIndex );
free( _p_stMergeData->d_p_stObject );
free( _p_stMergeData );
}
/****************************************************************************
* Description: add a super-object to the list of data to merge
*
* Parameters: _p_stMergeData : merge data to update
* _hSO : super-object to add
* _lGroupIndex : index of the element
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
void MLT_vMergeDataAddSO( tdstMergeData *_p_stMergeData, MLT_tdxHandleToSuperObject _hSO, long _lGroupIndex )
{
// if first element of group get merged object origin and move element at start of list
if (_lGroupIndex == 0)
{
MTH3D_M_vCopyVector( &_p_stMergeData->stOrigin, &_hSO->p_stMatrix->stTranslation );
if (_p_stMergeData->lNumberOfSO != 0)
{
_p_stMergeData->d_hSO[ _p_stMergeData->lNumberOfSO ] = _p_stMergeData->d_hSO[0];
_p_stMergeData->d_lIndex[ _p_stMergeData->lNumberOfSO ] = _p_stMergeData->d_lIndex[0];
}
_p_stMergeData->d_hSO[0] = _hSO;
_p_stMergeData->d_lIndex[0] = 0;
}
else
{
_p_stMergeData->d_hSO[ _p_stMergeData->lNumberOfSO ] = _hSO;
_p_stMergeData->d_lIndex[ _p_stMergeData->lNumberOfSO ] = _lGroupIndex;
}
_p_stMergeData->lNumberOfSO++;
}
/****************************************************************************
* Description: get index in group of a SO
*
* Parameters: _p_stMergeData : merge data to search
* _hSO : super-object to search
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
long MLT_lMergeDataGetSOIndex ( tdstMergeData *_p_stMergeData, MLT_tdxHandleToSuperObject _hSO )
{
long lIndex;
for (lIndex = 0; lIndex < _p_stMergeData->lNumberOfSO; lIndex++)
{
if ( _p_stMergeData->d_hSO[lIndex] == _hSO )
return _p_stMergeData->d_lIndex[lIndex];
}
return -1;
}
/****************************************************************************
* Description: get group index and name from a spo or object name
*
* Parameters: _szName : name to parse
* _szResultName : result name
*---------------------------------------------------------------------------
* Revision date: Author:
*****************************************************************************/
long MLT_lMergeGetIndexAndName ( char *_szName, char *_szResultName )
{
char *szGroupChar, *szEndGroup;
long lGroupIndex;
long lLength;
if ( (szGroupChar = strchr( _szName, '&')) == NULL )
return -1;
// it's a super object to be grouped
szEndGroup = szGroupChar + 1;
lGroupIndex = 0;
while ( 1 )
{
if (!isdigit(*szEndGroup))
break;
lGroupIndex = lGroupIndex*10 + *szEndGroup++ - '0';
}
// compute transformed name
lLength = szGroupChar - _szName;
memcpy( _szResultName, _szName, lLength );
strcpy( _szResultName + lLength, szEndGroup );
return lGroupIndex;
}