/*
0         1         2         3         4         5         6         7
01234567890123456789012345678901234567890123456789012345678901234567890123456789
--------------------------------------------------------------------------------
-- Description : Particles system
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
#ifndef D_THROW_PRT
 
#include "acp_base.h"
#include "MTH.h"
#include "RND.h"
#include "MEC.h"
#include "GMT.h"
#include "GEO.h"
#include "GLI.h"
#include "COL.h"
 
#include "PRT/SprtPrt.h"
 
extern float a64_fSinTable[64];
 
/*
--------------------------------------------------------------------------------
-- Description : Global variables
--------------------------------------------------------------------------------
*/
 
/*
--------------------------------------------------------------------------------
-- Description : Sprite particles creation
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vCreateSpriteParticles ( PRT_tdstParticlesSystem *_p_stParticlesSystem, ACP_tdxHandleOfSprite _hSprite )
{
  ACP_tdxHandleOfElement hElementSprite;
  ACP_tdxIndex xSpriteIndex;
  MTH2D_tdstVector stDefaultSize = { MTH_C_ONE, MTH_C_ONE };
  PRT_tdstSpriteCommonData *p_stSpriteCommonData;
 
  _p_stParticlesSystem->xParticlesType = PRT_C_xSpriteParticles;
 
  /* Table de vitesse de particules */
  GEO_M_CPAMalloc ( _p_stParticlesSystem->d_stSpeed,
                    MTH3D_tdstVector *,
                    sizeof ( MTH3D_tdstVector ) * _p_stParticlesSystem->xNbParticles,
                    E_uwGEONotEnoughtMemory );
 
  GEO_M_CPAMalloc ( _p_stParticlesSystem->d_stListOfParticles,
                    void *,
                    sizeof ( PRT_tdstSpriteParticle ) * _p_stParticlesSystem->xNbParticles,
                    E_uwGEONotEnoughtMemory );
 
  GEO_M_CPAMalloc ( _p_stParticlesSystem->p_stCommonData,
                    void *,
                    sizeof ( PRT_tdstSpriteCommonData ),
                    E_uwGEONotEnoughtMemory );
 
  GEO_vCreateGeometricObject ( &(_p_stParticlesSystem->hParticlesSystemObject), _p_stParticlesSystem->xNbParticles, 1 );
  GEO_vCreateElementSprite ( _p_stParticlesSystem->hParticlesSystemObject, &hElementSprite, _p_stParticlesSystem->xNbParticles );
	/*ANNECY VL PRT 18/03/98{*/
	((GEO_tdstElementSprite *) _p_stParticlesSystem->hParticlesSystemObject->d_stListOfElements[0])->cFastDraw = 1;
	/*ENDANNECY VL}*/
  for ( xSpriteIndex = 0 ; xSpriteIndex < _p_stParticlesSystem->xNbParticles ; xSpriteIndex ++ )
  {
    GEO_vSetSizeOfIndexedSprite ( _p_stParticlesSystem->hParticlesSystemObject, hElementSprite, xSpriteIndex, &stDefaultSize );
    GEO_vSetCenterPointOfIndexedSprite ( _p_stParticlesSystem->hParticlesSystemObject, hElementSprite, xSpriteIndex, xSpriteIndex );
    GEO_vSetHandleOfIndexedSprite ( _p_stParticlesSystem->hParticlesSystemObject, hElementSprite, xSpriteIndex, _hSprite );
  }
  GEO_vEndCreateObject ( _p_stParticlesSystem->hParticlesSystemObject );
 
  p_stSpriteCommonData = (PRT_tdstSpriteCommonData *)(_p_stParticlesSystem->p_stCommonData);
  p_stSpriteCommonData->hSprite = _hSprite;
}
 
/*
--------------------------------------------------------------------------------
-- Description : Sprite particles destruction
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void PRT_fn_vDestructSpriteParticles ( PRT_tdstParticlesSystem *_p_stParticlesSystem )
{
	PRT_tdstSpriteCommonData *p_stSpriteCommonData;
  
	_p_stParticlesSystem->xParticlesType = PRT_C_xNullParticles;
 
	/* Table de vitesse de particules */
	GEO_M_CPAFree ( _p_stParticlesSystem->d_stSpeed );
	_p_stParticlesSystem->d_stSpeed = NULL;
 
	GEO_M_CPAFree ( _p_stParticlesSystem->d_stListOfParticles );
	_p_stParticlesSystem->d_stListOfParticles = NULL;
 
	p_stSpriteCommonData = (PRT_tdstSpriteCommonData *) _p_stParticlesSystem->p_stCommonData;
	if ( p_stSpriteCommonData->d_stSpriteData != NULL )
		GEO_M_CPAFree ( p_stSpriteCommonData->d_stSpriteData );
 
	GEO_M_CPAFree ( p_stSpriteCommonData );
	_p_stParticlesSystem->p_stCommonData = NULL;
 
	GEO_vDeleteGeometricObject ( &(_p_stParticlesSystem->hParticlesSystemObject) );
	_p_stParticlesSystem->hParticlesSystemObject = NULL;
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vSetGameMaterialSpriteParticles ( PRT_tdstParticlesSystem *_p_stParticlesSystem,
                                              GMT_tdxHandleToGameMaterial _hGameMaterial )
{
  PRT_tdstSpriteCommonData *p_stSpriteCommonData;
 
  p_stSpriteCommonData = (PRT_tdstSpriteCommonData *)(_p_stParticlesSystem->p_stCommonData);
  p_stSpriteCommonData->hMaterial = _hGameMaterial;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vGenerateSpriteParticle 
		( 
			MTH3D_tdstVector			*_p_stParticlePosition,
            MTH3D_tdstVector			*_p_stParticleSpeed,
            PRT_tdstSpriteParticle		*_p_stSpriteParticle,
            PRT_tdstSpriteCommonData	*_p_stSpriteCommonData,
            PRT_tdstParticlesSource		*_p_stParticlesSource,
            POS_tdstCompletePosition	*_p_stSourceMatrix,
            MTH_tdxReal					_xTimeT 
		)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	MTH3D_tdstVector	stSpeedVariation;
	MTH_tdxReal			xC1, xC2, xC3, xC4;
	MTH3D_tdstVector	stTrans;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	/* vecteur variation de vitesse */
	MTH3D_M_vSetVectorElements 
		( 
			&stSpeedVariation,
			RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( _p_stParticlesSource->xSpeedRange ), _p_stParticlesSource->xSpeedRange ),
			RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( _p_stParticlesSource->xSpeedRange ), _p_stParticlesSource->xSpeedRange ),
			RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( _p_stParticlesSource->xSpeedRange ), _p_stParticlesSource->xSpeedRange ) 
		);
 
	/* vitesse initiale */
	MTH3D_M_vMullAddVector ( _p_stParticleSpeed, _p_stParticlesSource->xSpeed, &(_p_stParticlesSource->stNormal), &stSpeedVariation );
	if ( (_p_stParticlesSource->ucLinkMode == PRT_C_ucRotationLink) || (_p_stParticlesSource->ucLinkMode == PRT_C_ucRotAndTransLink) )
	{
		POS_fn_vMulMatrixVector ( _p_stParticleSpeed, _p_stSourceMatrix, _p_stParticleSpeed );
	}
 
	/* position initiale */
	if ( _p_stParticlesSource->ucGeometryMode == PRT_C_ucPoint )
	{
		MTH3D_M_vCopyVector ( _p_stParticlePosition, &(_p_stParticlesSource->stVertex1) );
	}
	else
	if ( _p_stParticlesSource->ucGeometryMode == PRT_C_ucQuad )
	{
		/* genere les deux parametres */
		xC2 = RND_fn_xGetRealRandomValue ( 0, MTH_C_ZERO, MTH_C_ONE );
		xC3 = RND_fn_xGetRealRandomValue ( 0, MTH_C_ZERO, MTH_C_ONE );
		xC1 = MTH_M_xSub ( MTH_M_xSub ( MTH_C_ONE, xC2 ), xC3 );
		_p_stParticlePosition->xX = xC1*_p_stParticlesSource->stVertex1.xX + xC2*_p_stParticlesSource->stVertex2.xX + xC3*_p_stParticlesSource->stVertex3.xX;
		_p_stParticlePosition->xY = xC1*_p_stParticlesSource->stVertex1.xY + xC2*_p_stParticlesSource->stVertex2.xY + xC3*_p_stParticlesSource->stVertex3.xY;
		_p_stParticlePosition->xZ = xC1*_p_stParticlesSource->stVertex1.xZ + xC2*_p_stParticlesSource->stVertex2.xZ + xC3*_p_stParticlesSource->stVertex3.xZ;
	}
	else if ( _p_stParticlesSource->ucGeometryMode == PRT_C_ucParallelepipede )
	{
		/* genere les deux parametres */
		xC2 = RND_fn_xGetRealRandomValue ( 0, MTH_C_ZERO, MTH_C_ONE );
		xC3 = RND_fn_xGetRealRandomValue ( 0, MTH_C_ZERO, MTH_C_ONE );
		xC4 = RND_fn_xGetRealRandomValue ( 0, MTH_C_ZERO, MTH_C_ONE );
		xC1 = MTH_M_xSub ( MTH_M_xSub ( MTH_M_xSub ( MTH_C_ONE, xC2 ), xC3 ), xC4 );
		_p_stParticlePosition->xX = xC1*_p_stParticlesSource->stVertex1.xX + xC2*_p_stParticlesSource->stVertex2.xX + xC3*_p_stParticlesSource->stVertex3.xX + xC4*_p_stParticlesSource->stVertex4.xX;
		_p_stParticlePosition->xY = xC1*_p_stParticlesSource->stVertex1.xY + xC2*_p_stParticlesSource->stVertex2.xY + xC3*_p_stParticlesSource->stVertex3.xY + xC4*_p_stParticlesSource->stVertex4.xY;
		_p_stParticlePosition->xZ = xC1*_p_stParticlesSource->stVertex1.xZ + xC2*_p_stParticlesSource->stVertex2.xZ + xC3*_p_stParticlesSource->stVertex3.xZ + xC4*_p_stParticlesSource->stVertex4.xZ;
	}
 
	if ( _p_stParticlesSource->ucLinkMode == PRT_C_ucRotAndTransLink )
	{
		POS_fn_vMulMatrixVertex( _p_stParticlePosition, _p_stSourceMatrix, _p_stParticlePosition );
	}
	else if ( _p_stParticlesSource->ucLinkMode == PRT_C_ucTranslationLink )
	{
		POS_fn_vGetTranslationVector( _p_stSourceMatrix, &stTrans );
		MTH3D_M_vAddVector ( _p_stParticlePosition, &stTrans, _p_stParticlePosition );
	}
	else if ( _p_stParticlesSource->ucLinkMode == PRT_C_ucRotationLink )
	{
		POS_fn_vMulMatrixVector ( _p_stParticlePosition, _p_stSourceMatrix, _p_stParticlePosition );
	}
 
	/* DeathDate */
	if ( _p_stParticlesSource->ucLifeMode == PRT_C_ucNoLifeTime )
	{
		_p_stSpriteParticle->xDeathDate = MTH_C_InfinitPlus;
	}
	else if ( _p_stParticlesSource->ucLifeMode == PRT_C_ucConstantLifeTime )
	{
		_p_stSpriteParticle->xDeathDate = MTH_M_xAdd ( _xTimeT, _p_stParticlesSource->xMinTime );
	}
	else if ( _p_stParticlesSource->ucLifeMode == PRT_C_ucProbabilistLifeTime )
	{
		_p_stSpriteParticle->xDeathDate = MTH_M_xAdd ( _xTimeT, RND_fn_xGetRealRandomValue ( 0, _p_stParticlesSource->xMinTime, _p_stParticlesSource->xMaxTime ) );
	}
	/* particle rotation */
	{
		static int iRotation = 0;
		if (iRotation)
		{
			_p_stSpriteParticle->a2_cRotateSpeed[0] = (char) (RND_fn_ulGetUnsignedLongRandomValue( 0, 0, 9) - 4 );
			_p_stSpriteParticle->a2_cRotateSpeed[1] = (char) (RND_fn_ulGetUnsignedLongRandomValue( 0, 0, 9) - 4 );
		}
	}
}
 
/*
--------------------------------------------------------------------------------
 Description : add a particle in a particle generator
--------------------------------------------------------------------------------
 Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
void PRT_fn_vAddSpriteParticle( tdstParticleGenerator *_p_stPrtGen, MTH3D_tdstVector *_p_stParticlePosition, MTH3D_tdstVector *_p_stParticleSpeed, MTH_tdxReal _xTime )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	MTH3D_tdstVector			*p_stVect;
	PRT_tdstParticlesSystem		*p_stPrtSys;
	PRT_tdstParticlesSource		*p_stPrtSrc;
	PRT_tdstSpriteParticle		*p_stSprPrt;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	p_stPrtSys = _p_stPrtGen->p_stPrtSys;
	if (p_stPrtSys->xNbActiveParticles == p_stPrtSys->xNbParticles)
		return;
    
	/* DeathDate */
	p_stPrtSrc = _p_stPrtGen->p_stPrtSrc;
	p_stSprPrt = (PRT_tdstSpriteParticle *)(p_stPrtSys->d_stListOfParticles) + p_stPrtSys->xNbActiveParticles;
	if ( p_stPrtSrc->ucLifeMode == PRT_C_ucNoLifeTime )
		p_stSprPrt->xDeathDate = MTH_C_InfinitPlus;
	else if ( p_stPrtSrc->ucLifeMode == PRT_C_ucConstantLifeTime )
		p_stSprPrt->xDeathDate = MTH_M_xAdd ( _xTime, p_stPrtSrc->xMinTime );
	else if ( p_stPrtSrc->ucLifeMode == PRT_C_ucProbabilistLifeTime )
		p_stSprPrt->xDeathDate = MTH_M_xAdd ( _xTime, RND_fn_xGetRealRandomValue ( 0, p_stPrtSrc->xMinTime, p_stPrtSrc->xMaxTime ) );
 
    p_stVect = p_stPrtSys->hParticlesSystemObject->d_stListOfPoints + p_stPrtSys->xNbActiveParticles;
	MTH3D_M_vCopyVector( p_stVect, _p_stParticlePosition );
    p_stVect = p_stPrtSys->d_stSpeed + p_stPrtSys->xNbActiveParticles;
	MTH3D_M_vCopyVector( p_stVect, _p_stParticleSpeed );
    p_stPrtSys->xNbActiveParticles++;
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
void PRT_fn_vMecaSpriteParticlesSystem ( tdstParticleGenerator *_p_stPrtGen,MTH_tdxReal _xTimeT,MTH_tdxReal _xDeltaT )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	PRT_tdstSpriteParticle			*p_stSpriteParticle,	*p_stLastSpriteParticle;
	MTH3D_tdstVector				*p_stParticlePosition,	*p_stLastParticlePosition;
	MTH3D_tdstVector				*p_stParticleSpeed,		*p_stLastParticleSpeed;
	ACP_tdxBool						bAlivedParticle;
	MTH3D_tdstVector				stAccelerationVariation;
	PRT_tdstParticlesEnvironment	*p_stPrtEnv;
	PRT_tdstParticlesSystem			*p_stPrtSys;
/*XB980505*/
/*	GEO_tdstIndexedSprite			*p_stGeoSprite,			*p_stLastGeoSprite;*/
	GEO_tdstIndexedSprite			*p_stGeoSprite,			*p_stLastGeoSprite=NULL;
/*End XB*/
	PRT_tdstSpriteData				*p_stSprData;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	p_stPrtEnv = _p_stPrtGen->p_stPrtEnv;
	p_stPrtSys = _p_stPrtGen->p_stPrtSys;
 
	p_stSpriteParticle			= (PRT_tdstSpriteParticle *)(p_stPrtSys->d_stListOfParticles);
	p_stLastSpriteParticle		= p_stSpriteParticle + p_stPrtSys->xNbActiveParticles;
	p_stParticlePosition		= p_stPrtSys->hParticlesSystemObject->d_stListOfPoints;
	p_stLastParticlePosition	= p_stParticlePosition + p_stPrtSys->xNbActiveParticles;
	p_stParticleSpeed			= p_stPrtSys->d_stSpeed;
	p_stLastParticleSpeed		= p_stParticleSpeed + p_stPrtSys->xNbActiveParticles;
 
	if (PRT_fn_cSystemIsMultipleSprites( p_stPrtSys) )
	{
		p_stGeoSprite			= ((GEO_tdstElementSprite *) p_stPrtSys->hParticlesSystemObject->d_stListOfElements[0])->d_stListOfSprites;
		p_stLastGeoSprite		= p_stGeoSprite	+ p_stPrtSys->xNbActiveParticles;
	}
	else
		p_stGeoSprite = NULL;
 
	while ( p_stSpriteParticle != p_stLastSpriteParticle )
	{
		/* first test death date */
		bAlivedParticle = MTH_M_bGreater ( p_stSpriteParticle->xDeathDate, _xTimeT );
		if (bAlivedParticle)
		{
			/* appliquer la meca */
			/* vecteur variation de l acceleration */
			MTH3D_M_vSetVectorElements 
				( 
					&stAccelerationVariation,
					RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( p_stPrtEnv->xAccelerationRange ), p_stPrtEnv->xAccelerationRange ),
					RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( p_stPrtEnv->xAccelerationRange ), p_stPrtEnv->xAccelerationRange ),
					RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( p_stPrtEnv->xAccelerationRange ), p_stPrtEnv->xAccelerationRange ) 
				);
			MTH3D_M_vAddVector ( &stAccelerationVariation, &(p_stPrtEnv->stAcceleration), &stAccelerationVariation );
 
			/* Vit t = f( Vit t-1, Pos t-1, Accel t ) */
			MTH3D_M_vMullAddVector ( p_stParticleSpeed, _xDeltaT, &stAccelerationVariation, p_stParticleSpeed );
			/* Pos t = f( Vit t, Pos t-1, Accel t ) */
			MTH3D_M_vMullAddVector ( p_stParticlePosition, _xDeltaT, p_stParticleSpeed, p_stParticlePosition );
 
			bAlivedParticle = 
				( p_stPrtEnv->ulEnvType == PRT_C_ulAlignedBoxEnv ) ? 
				INT_fn_bGetInclusionPointInBox ( p_stParticlePosition, &(p_stPrtEnv->stMinPoint), &(p_stPrtEnv->stMaxPoint) ) :
				INT_fn_bGetInclusionPointInSphere ( p_stParticlePosition,&(p_stPrtEnv->stSphereCenter),p_stPrtEnv->xRadius );
		}
 
		if ( bAlivedParticle )
		{
			/*
			 * treatment on alive particle that have not to be done to death particles
			 */
			/* rotation */
			if (p_stSpriteParticle->a2_cRotateSpeed[0])
			{
				p_stSpriteParticle->a2_ucRotateAngle[0] += p_stSpriteParticle->a2_cRotateSpeed[0];
				p_stGeoSprite->stSize.xX = p_stSpriteParticle->stSize.xX * a64_fSinTable[ p_stSpriteParticle->a2_ucRotateAngle[0] & 0x3F ] / 2;
			}
 
			if (p_stSpriteParticle->a2_cRotateSpeed[1])
			{
				p_stSpriteParticle->a2_ucRotateAngle[1] += p_stSpriteParticle->a2_cRotateSpeed[1];
				p_stGeoSprite->stSize.xY = p_stSpriteParticle->stSize.xY * a64_fSinTable[ p_stSpriteParticle->a2_ucRotateAngle[1] & 0x3F ] / 2;
			}
			/* change sprite */
			if ( p_stGeoSprite && MTH_M_bGreater( _xTimeT, p_stSpriteParticle->xChangeSpriteDate ) )
			{
				p_stSprData = ((PRT_tdstSpriteCommonData *) p_stPrtSys->p_stCommonData)->d_stSpriteData + p_stSpriteParticle->cNextSpriteIndex;
				p_stGeoSprite->hSprite = p_stSprData->hSprite;
				if ( p_stSprData->xTime < 0 )
					p_stSpriteParticle->xChangeSpriteDate = MTH_C_InfinitPlus;
				else
				{
					p_stSpriteParticle->xChangeSpriteDate = _xTimeT + p_stSprData->xTime;
					p_stSpriteParticle->cNextSpriteIndex = p_stSprData->cNextSprite;
				}
			}
 
			/*
			 * goto next particle
			 */
			p_stSpriteParticle ++;
			p_stParticlePosition ++;
			p_stParticleSpeed ++;
			if (p_stGeoSprite)
				p_stGeoSprite++;
		}
		else
		{
			p_stPrtSys->xNbActiveParticles --;
			p_stLastSpriteParticle --;
 
			/*
			 * If there's a linked generator add this particle to linked generator
			 */
			if (_p_stPrtGen->p_stLinkedPrtGen)
			{
				if (_p_stPrtGen->ulLinkedPrtGenMask & 1 )
					MTH3D_M_vNullVector( p_stParticleSpeed );
				PRT_fn_vAddSpriteParticle( _p_stPrtGen->p_stLinkedPrtGen, p_stParticlePosition, p_stParticleSpeed, _xTimeT );
			}
 
			if ( p_stSpriteParticle != p_stLastSpriteParticle )
			{
				*p_stSpriteParticle = *p_stLastSpriteParticle;
				p_stLastParticlePosition --;
				*p_stParticlePosition = *p_stLastParticlePosition;
				p_stLastParticleSpeed --;
				*p_stParticleSpeed = *p_stLastParticleSpeed;
				if (p_stGeoSprite)
					p_stGeoSprite->hSprite = (--p_stLastGeoSprite)->hSprite;
			}
		}
	}
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vSourceGenerateSpriteParticle 
		( 
			PRT_tdstParticlesSystem *_p_stParticlesSystem,
            PRT_tdstParticlesSource *_p_stParticlesSource,
            POS_tdstCompletePosition *_p_stSourceMatrix,
            MTH_tdxReal _xTimeT 
		)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	PRT_tdstSpriteParticle		*p_stSpriteParticle;
	MTH3D_tdstVector			*p_stParticlePosition;
	MTH3D_tdstVector			*p_stParticleSpeed;
	ACP_tdxIndex				xNbParticlesToInject;
	ACP_tdxIndex				xIndex;
	ACP_tdxIndex				xSpriteIndex;
	PRT_tdstSpriteCommonData	*p_stSpriteCommonData;
	PRT_tdstSpriteData			*p_stSprData;
	char						cProba;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	/* generation de particules ? */
	if ( PRT_fn_bComputeParticlesGeneration ( _p_stParticlesSource ) )
	{
		xNbParticlesToInject = (ACP_tdxIndex) MTH_M_xRealToLong ( MTH_M_xMul ( MTH_M_xLongToReal ( PRT_fn_xComputeNbParticlesToInject ( _p_stParticlesSource ) ), PRT_g_xNbParticlesFactor ) );
 
		if ( xNbParticlesToInject > 0 )
		{
			if ( _p_stParticlesSystem->xNbActiveParticles + xNbParticlesToInject > _p_stParticlesSystem->xNbParticles )
			{
				xNbParticlesToInject = _p_stParticlesSystem->xNbParticles - _p_stParticlesSystem->xNbActiveParticles;
			}
 
			p_stSpriteCommonData = (PRT_tdstSpriteCommonData *)(_p_stParticlesSystem->p_stCommonData);
			p_stSpriteParticle = (PRT_tdstSpriteParticle *)(_p_stParticlesSystem->d_stListOfParticles) + _p_stParticlesSystem->xNbActiveParticles;
			p_stParticlePosition = _p_stParticlesSystem->hParticlesSystemObject->d_stListOfPoints + _p_stParticlesSystem->xNbActiveParticles;
			p_stParticleSpeed = _p_stParticlesSystem->d_stSpeed + _p_stParticlesSystem->xNbActiveParticles;
			xSpriteIndex = _p_stParticlesSystem->xNbActiveParticles;
			_p_stParticlesSystem->xNbActiveParticles += xNbParticlesToInject;
 
			for ( xIndex = 0 ; xIndex < xNbParticlesToInject ; xIndex ++ )
			{
				/* reset meca */
				PRT_fn_vGenerateSpriteParticle 
					( 
						p_stParticlePosition, 
						p_stParticleSpeed,
                        p_stSpriteParticle, 
						p_stSpriteCommonData,
						_p_stParticlesSource, 
						_p_stSourceMatrix, 
						_xTimeT 
					);
 
				/* special for multi sprite particles : to be deplaced in generation part code */
				if ( (p_stSprData = p_stSpriteCommonData->d_stSpriteData) != NULL )
				{
					cProba = (char) RND_fn_ulGetUnsignedLongRandomValue( 0, 0, 100 );
					while (p_stSprData->cProba <= cProba )
						p_stSprData++;
					
					GEO_vSetHandleOfIndexedSprite( _p_stParticlesSystem->hParticlesSystemObject, 0, xSpriteIndex, p_stSprData->hSprite );
					
					if (p_stSprData->xTime < 0)
						p_stSpriteParticle->xChangeSpriteDate = MTH_C_InfinitPlus;
					else
					{
						p_stSpriteParticle->xChangeSpriteDate = _xTimeT + p_stSprData->xTime;
						p_stSpriteParticle->cNextSpriteIndex  = p_stSprData->cNextSprite;
					}
					
					xSpriteIndex++;
				}
				/* end multi sprite special code */
 
				p_stSpriteParticle ++;
				p_stParticlePosition ++;
				p_stParticleSpeed ++;
			}
		}
	}
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vPreDrawSpriteParticlesSystem ( PRT_tdstParticlesSystem *_p_stParticlesSystem )
{
  _p_stParticlesSystem->hParticlesSystemObject->xNbPoints = _p_stParticlesSystem->xNbActiveParticles;
  ((GEO_tdstElementSprite *)(_p_stParticlesSystem->hParticlesSystemObject->d_stListOfElements[0]))->xNbSprites = _p_stParticlesSystem->xNbActiveParticles;
}
 
 
/*ANNECY VL PRT 30/03/98{*/
 
/*
 ----------------------------------------------------------------------------------------
  Description   : create multiple sprites particles system
  _p_stPrtSys         -> system
  _xNbSprites         -> number of different sprites
 ----------------------------------------------------------------------------------------
 */
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void PRT_fn_vCreateMultipleSpritesParticles( PRT_tdstParticlesSystem *_p_stPrtSys, ACP_tdxIndex _xNbSprites )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	PRT_tdstSpriteCommonData	*p_stSprCommonData;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	_p_stPrtSys->xParticlesType = PRT_C_xSpriteParticles;
 
	/* Table de vitesse de particules */
	GEO_M_CPAMalloc ( _p_stPrtSys->d_stSpeed, MTH3D_tdstVector *, sizeof ( MTH3D_tdstVector ) * _p_stPrtSys->xNbParticles, E_uwGEONotEnoughtMemory );
	/* list of sprite particles */
	GEO_M_CPAMalloc ( _p_stPrtSys->d_stListOfParticles, void *, sizeof ( PRT_tdstSpriteParticle ) * _p_stPrtSys->xNbParticles, E_uwGEONotEnoughtMemory );
	/* common data for sprite system */
	GEO_M_CPAMalloc ( _p_stPrtSys->p_stCommonData, void *, sizeof ( PRT_tdstSpriteCommonData ), E_uwGEONotEnoughtMemory );
	p_stSprCommonData = (PRT_tdstSpriteCommonData *)(_p_stPrtSys->p_stCommonData);
	/* common data for sprite system */
	GEO_M_CPAMalloc ( p_stSprCommonData->d_stSpriteData, PRT_tdstSpriteData *, _xNbSprites * sizeof( PRT_tdstSpriteData ), E_uwGEONotEnoughtMemory );
	p_stSprCommonData->xNumberOfSprites = 0;
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : end creation of multiple sprite particles system (create geom object)
  _p_stPrtSys         -> system
 ----------------------------------------------------------------------------------------
 */
void PRT_fn_vEndCreateMultipleSpritesParticles( PRT_tdstParticlesSystem *_p_stPrtSys )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	ACP_tdxHandleOfElement		hElementSprite;
	ACP_tdxIndex				xSpriteIndex;
	MTH2D_tdstVector			stDefaultSize = { MTH_C_ONE, MTH_C_ONE };
	PRT_tdstSpriteCommonData	*p_stSprCommonData;
	PRT_tdstSpriteParticle		*p_stSprParticle;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	if (_p_stPrtSys->xParticlesType != PRT_C_xSpriteParticles )
		return;
 
  
	GEO_vCreateGeometricObject ( &(_p_stPrtSys->hParticlesSystemObject), _p_stPrtSys->xNbParticles, 1 );
	GEO_vCreateElementSprite ( _p_stPrtSys->hParticlesSystemObject, &hElementSprite, _p_stPrtSys->xNbParticles );
	((GEO_tdstElementSprite *) _p_stPrtSys->hParticlesSystemObject->d_stListOfElements[0])->cFastDraw = 1;
	
	p_stSprCommonData = (PRT_tdstSpriteCommonData *) _p_stPrtSys->p_stCommonData;
	p_stSprParticle = _p_stPrtSys->d_stListOfParticles;
  
	for ( xSpriteIndex = 0 ; xSpriteIndex < _p_stPrtSys->xNbParticles ; xSpriteIndex ++, p_stSprParticle++ )
	{
		GEO_vSetSizeOfIndexedSprite			( _p_stPrtSys->hParticlesSystemObject, hElementSprite, xSpriteIndex, &stDefaultSize );
		GEO_vSetCenterPointOfIndexedSprite	( _p_stPrtSys->hParticlesSystemObject, hElementSprite, xSpriteIndex, xSpriteIndex );
		GEO_vSetHandleOfIndexedSprite		( _p_stPrtSys->hParticlesSystemObject, hElementSprite, xSpriteIndex, p_stSprCommonData->d_stSpriteData[ xSpriteIndex % p_stSprCommonData->xNumberOfSprites ].hSprite );
		p_stSprParticle->stSize = stDefaultSize;
	}
	GEO_vEndCreateObject ( _p_stPrtSys->hParticlesSystemObject );
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : Test if system is a multiple sprite particle system
  _p_stPrtSys         -> system
  Returns (char ) : 0 if false, otherwise 0
 ----------------------------------------------------------------------------------------
 */
char PRT_fn_cSystemIsMultipleSprites( PRT_tdstParticlesSystem *_p_stPrtSys )
{
	if (_p_stPrtSys->xParticlesType != PRT_C_xSpriteParticles )
		return 0;
	return ( ((PRT_tdstSpriteCommonData *) _p_stPrtSys->p_stCommonData)->d_stSpriteData != NULL );
}
 
 
/*
 ----------------------------------------------------------------------------------------
  Description   : add a sprite in a multiple sprite particle system
  _p_stPrtSys         -> system
  _hSprite            -> sprite
 ----------------------------------------------------------------------------------------
 */
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void PRT_fn_vAddSprite( PRT_tdstParticlesSystem *_p_stPrtSys, ACP_tdxHandleOfSprite _hSprite )
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	PRT_tdstSpriteCommonData	*p_stSpriteCommonData;
	PRT_tdstSpriteData			*p_stSprData;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
	if (_p_stPrtSys->xParticlesType != PRT_C_xSpriteParticles )
		return;
 
	p_stSpriteCommonData = (PRT_tdstSpriteCommonData *) _p_stPrtSys->p_stCommonData;
	p_stSprData = p_stSpriteCommonData->d_stSpriteData + p_stSpriteCommonData->xNumberOfSprites++;
	p_stSprData->hSprite = _hSprite;
 
	if (p_stSpriteCommonData->xNumberOfSprites == 1)
	{
		p_stSprData->cProba = 100;
		p_stSprData->xTime  = 2;
		p_stSprData->cNextSprite = 1;
	}
	else if (p_stSpriteCommonData->xNumberOfSprites == 5)
	{
		p_stSprData->cProba = 0;
		p_stSprData->xTime  = 0.1f;
		p_stSprData->cNextSprite = 0;
	}
	else
	{
		p_stSprData->cProba = 0;
		p_stSprData->xTime  = 0.1f;
		p_stSprData->cNextSprite = (char)(p_stSpriteCommonData->xNumberOfSprites);
	}
 
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
#endif /* D_THROW_PRT */
