/*
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/PointPrt.h"
 
/*
--------------------------------------------------------------------------------
-- Description : Global variables
--------------------------------------------------------------------------------
*/
 
/*
--------------------------------------------------------------------------------
-- Description : Point particles creation
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vCreatePointParticles ( PRT_tdstParticlesSystem *_p_stParticlesSystem,
                                    GMT_tdxHandleToGameMaterial _hMaterial )
{
  ACP_tdxHandleOfElement hElementPoint;
  ACP_tdxIndex xPointIndex;
  GEO_tdstColor stColor;
  PRT_tdstPointCommonData *p_stPointCommonData;
 
  _p_stParticlesSystem->xParticlesType = PRT_C_xPointParticles;
 
  /* 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_tdstPointParticle ) * _p_stParticlesSystem->xNbParticles,
                    E_uwGEONotEnoughtMemory );
 
  GEO_M_CPAMalloc ( _p_stParticlesSystem->p_stCommonData,
                    void *,
                    sizeof ( PRT_tdstPointCommonData ),
                    E_uwGEONotEnoughtMemory );
 
  stColor.xR = 1.0f;
  stColor.xG = 1.0f;
  stColor.xB = 1.0f;
  stColor.xA = 1.0f;
 
  GEO_vCreateGeometricObject ( &(_p_stParticlesSystem->hParticlesSystemObject), _p_stParticlesSystem->xNbParticles, 1 );
  GEO_xCreateElementPoints ( _p_stParticlesSystem->hParticlesSystemObject, &hElementPoint, _p_stParticlesSystem->xNbParticles );
  GEO_xSetGameMaterialOfElementPoints ( _p_stParticlesSystem->hParticlesSystemObject, hElementPoint, _hMaterial );
 
  for ( xPointIndex = 0 ; xPointIndex < _p_stParticlesSystem->xNbParticles ; xPointIndex ++ )
  {
    GEO_xSetIndexOfElementPoints ( _p_stParticlesSystem->hParticlesSystemObject, hElementPoint, xPointIndex, xPointIndex );
  }
  GEO_vEndCreateObject ( _p_stParticlesSystem->hParticlesSystemObject );
 
  p_stPointCommonData = (PRT_tdstPointCommonData *)(_p_stParticlesSystem->p_stCommonData);
  p_stPointCommonData->hMaterial = _hMaterial;
}
 
/*
--------------------------------------------------------------------------------
-- Description : Point particles destruction
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void PRT_fn_vDestructPointParticles ( PRT_tdstParticlesSystem *_p_stParticlesSystem )
{
  _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;
 
  GEO_M_CPAFree ( _p_stParticlesSystem->p_stCommonData );
  _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_vSetGameMaterialPointParticles ( PRT_tdstParticlesSystem *_p_stParticlesSystem,
                                             GMT_tdxHandleToGameMaterial _hGameMaterial )
{
  PRT_tdstPointCommonData *p_stPointCommonData;
 
  p_stPointCommonData = (PRT_tdstPointCommonData *)(_p_stParticlesSystem->p_stCommonData);
  p_stPointCommonData->hMaterial = _hGameMaterial;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vGeneratePointParticle ( MTH3D_tdstVector *_p_stParticlePosition,
                                     MTH3D_tdstVector *_p_stParticleSpeed,
                                     PRT_tdstPointParticle *_p_stPointParticle,
                                     PRT_tdstPointCommonData *_p_stPointCommonData,
                                     PRT_tdstParticlesSource *_p_stParticlesSource,
                                     POS_tdstCompletePosition *_p_stSourceMatrix,
                                     MTH_tdxReal _xTimeT )
{
  MTH3D_tdstVector stSpeedVariation;
  MTH_tdxReal xC1;
  MTH_tdxReal xC2;
  MTH_tdxReal xC3;
  MTH_tdxReal 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 );
  }
 
  /* BirthDate */
/*  p_stBubbleParticle->xBirthDate = xTimeT;*/
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vMecaPointParticlesSystem ( PRT_tdstParticlesSystem *_p_stParticlesSystem,
                                        PRT_tdstParticlesEnvironment *_p_stParticlesEnvironment,
                                        MTH_tdxReal _xTimeT,
                                        MTH_tdxReal _xDeltaT )
{
  PRT_tdstPointParticle *p_stPointParticle;
  PRT_tdstPointParticle *p_stLastPointParticle;
  MTH3D_tdstVector *p_stParticlePosition;
  MTH3D_tdstVector *p_stLastParticlePosition;
  MTH3D_tdstVector *p_stParticleSpeed;
  MTH3D_tdstVector *p_stLastParticleSpeed;
  ACP_tdxBool bAlivedParticle;
  MTH3D_tdstVector stAccelerationVariation;
 
  p_stPointParticle = (PRT_tdstPointParticle *)(_p_stParticlesSystem->d_stListOfParticles);
  p_stLastPointParticle = p_stPointParticle + _p_stParticlesSystem->xNbActiveParticles;
  p_stParticlePosition = _p_stParticlesSystem->hParticlesSystemObject->d_stListOfPoints;
  p_stLastParticlePosition = p_stParticlePosition + _p_stParticlesSystem->xNbActiveParticles;
  p_stParticleSpeed = _p_stParticlesSystem->d_stSpeed;
  p_stLastParticleSpeed = p_stParticleSpeed + _p_stParticlesSystem->xNbActiveParticles;
 
  while ( p_stPointParticle != p_stLastPointParticle )
  {
    /* appliquer la meca */
    /* vecteur variation de l acceleration */
    MTH3D_M_vSetVectorElements ( &stAccelerationVariation,
      RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( _p_stParticlesEnvironment->xAccelerationRange ), _p_stParticlesEnvironment->xAccelerationRange ),
      RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( _p_stParticlesEnvironment->xAccelerationRange ), _p_stParticlesEnvironment->xAccelerationRange ),
      RND_fn_xGetRealRandomValue ( 0, MTH_M_xNeg ( _p_stParticlesEnvironment->xAccelerationRange ), _p_stParticlesEnvironment->xAccelerationRange ) );
 
    MTH3D_M_vAddVector ( &stAccelerationVariation, &(_p_stParticlesEnvironment->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_stParticlesEnvironment->ulEnvType == PRT_C_ulAlignedBoxEnv ) ?
                      INT_fn_bGetInclusionPointInBox ( p_stParticlePosition,
                                                       &(_p_stParticlesEnvironment->stMinPoint),
                                                       &(_p_stParticlesEnvironment->stMaxPoint) ) :
                      INT_fn_bGetInclusionPointInSphere ( p_stParticlePosition,
                                                          &(_p_stParticlesEnvironment->stSphereCenter),
                                                          _p_stParticlesEnvironment->xRadius );
    if ( bAlivedParticle )
    {
      p_stPointParticle ++;
      p_stParticlePosition ++;
      p_stParticleSpeed ++;
    }
    else
    {
      _p_stParticlesSystem->xNbActiveParticles --;
      p_stLastPointParticle --;
 
      if ( p_stPointParticle != p_stLastPointParticle )
      {
        *p_stPointParticle = *p_stLastPointParticle;
        p_stLastParticlePosition --;
        *p_stParticlePosition = *p_stLastParticlePosition;
        p_stLastParticleSpeed --;
        *p_stParticleSpeed = *p_stLastParticleSpeed;
      }
    }
  }
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vSourceGeneratePointParticle ( PRT_tdstParticlesSystem *_p_stParticlesSystem,
                                           PRT_tdstParticlesSource *_p_stParticlesSource,
                                           POS_tdstCompletePosition *_p_stSourceMatrix,
                                           MTH_tdxReal _xTimeT )
{
  PRT_tdstPointParticle *p_stPointParticle;
  MTH3D_tdstVector *p_stParticlePosition;
  MTH3D_tdstVector *p_stParticleSpeed;
  ACP_tdxIndex xNbParticlesToInject;
  ACP_tdxIndex xIndex;
 
  /* generation de particules ? */
  if ( PRT_fn_bComputeParticlesGeneration ( _p_stParticlesSource ) )
  {
    /*ANNECY VL PRT 18/03/98{*/
	xNbParticlesToInject = (ACP_tdxIndex) MTH_M_xRealToLong ( MTH_M_xMul ( MTH_M_xLongToReal ( PRT_fn_xComputeNbParticlesToInject ( _p_stParticlesSource ) ), PRT_g_xNbParticlesFactor ) );
	/*ENDANNECY VL}*/
 
    if ( xNbParticlesToInject > 0 )
    {
      if ( _p_stParticlesSystem->xNbActiveParticles + xNbParticlesToInject > _p_stParticlesSystem->xNbParticles )
      {
        xNbParticlesToInject = _p_stParticlesSystem->xNbParticles - _p_stParticlesSystem->xNbActiveParticles;
      }
 
      p_stPointParticle = (PRT_tdstPointParticle *)(_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;
      _p_stParticlesSystem->xNbActiveParticles += xNbParticlesToInject;
 
      for ( xIndex = 0 ; xIndex < xNbParticlesToInject ; xIndex ++ )
      {
        /* reset meca */
        PRT_fn_vGeneratePointParticle ( p_stParticlePosition, p_stParticleSpeed,
                                        p_stPointParticle, (PRT_tdstPointCommonData *)(_p_stParticlesSystem->p_stCommonData),
                                        _p_stParticlesSource, _p_stSourceMatrix, _xTimeT );
 
        p_stPointParticle ++;
        p_stParticlePosition ++;
        p_stParticleSpeed ++;
      }
    }
  }
}
 
/*
--------------------------------------------------------------------------------
-- Description : 
--------------------------------------------------------------------------------
-- Creation date : 12 jun 1997               Author : FPI
--------------------------------------------------------------------------------
*/
 
void PRT_fn_vPreDrawPointParticlesSystem ( PRT_tdstParticlesSystem *_p_stParticlesSystem )
{
  _p_stParticlesSystem->hParticlesSystemObject->xNbPoints = _p_stParticlesSystem->xNbActiveParticles;
  ((GEO_tdstElementPoints *)(_p_stParticlesSystem->hParticlesSystemObject->d_stListOfElements[0]))->xNbPoints = _p_stParticlesSystem->xNbActiveParticles;
}
 
#endif /* D_THROW_PRT */
