433 lines
16 KiB
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;
|
|
}
|
|
|
|
|