Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

606 lines
21 KiB

  1. //===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: particle system code
  4. //
  5. //===========================================================================//
  6. #include <algorithm>
  7. #include "tier0/platform.h"
  8. #include "tier0/vprof.h"
  9. #include "particles/particles.h"
  10. #include "particles_internal.h"
  11. #include "bitmap/psheet.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. #define SORTBUFSIZE0 (( MAX_PARTICLES_IN_A_SYSTEM + 4 ) * sizeof( ParticleRenderData_t ) )
  15. #define SORTBUFSIZE1 ( ( 1 + MAX_PARTICLES_IN_A_SYSTEM / 4 )* sizeof( ParticleFullRenderData_Scalar_View ) )
  16. #define SORTBUFSIZE2 ( ( 1 + MAX_PARTICLES_IN_A_SYSTEM / 4 )* sizeof( ParticleRenderDataWithOutlineInformation_Scalar_View ) )
  17. static ALIGN16 uint8 s_SortBuffer[ COMPILETIME_MAX( COMPILETIME_MAX( SORTBUFSIZE0, SORTBUFSIZE1 ), SORTBUFSIZE2 )] ALIGN16_POST;
  18. static ALIGN16 ParticleFullRenderData_Scalar_View *s_pParticlePtrs[MAX_PARTICLES_IN_A_SYSTEM] ALIGN16_POST;
  19. enum EParticleSortKeyType
  20. {
  21. SORT_KEY_NONE,
  22. SORT_KEY_DISTANCE,
  23. SORT_KEY_CREATION_TIME,
  24. };
  25. void C4VInterpolatedAttributeIterator::Init( int nAttribute, CParticleCollection *pParticles )
  26. {
  27. // initializing this is somewhat complicated by the behavior of prev_xyz and xyz
  28. m_pData = pParticles->Get4VAttributePtr( nAttribute, &m_nStride );
  29. Assert( pParticles->GetPrevAttributeMemory() );
  30. if ( m_nStride )
  31. {
  32. m_nOldDataOffset =
  33. pParticles->m_PreviousFrameAttributes.ByteAddress( nAttribute ) - pParticles->m_ParticleAttributes.ByteAddress( nAttribute );
  34. }
  35. else
  36. {
  37. // it's constant data
  38. m_nOldDataOffset = 0;
  39. }
  40. }
  41. template<EParticleSortKeyType eSortKeyMode, bool bCull> void s_GenerateData( void *pOutData, Vector CameraPos, Vector *pCameraFwd,
  42. CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles )
  43. {
  44. fltx4 *pOutUnSorted = reinterpret_cast<fltx4 *>( pOutData );
  45. C4VAttributeIterator pXYZ( PARTICLE_ATTRIBUTE_XYZ, pParticles );
  46. CM128AttributeIterator pCreationTimeStamp( PARTICLE_ATTRIBUTE_CREATION_TIME, pParticles );
  47. CM128AttributeIterator pAlpha( PARTICLE_ATTRIBUTE_ALPHA, pParticles );
  48. CM128AttributeIterator pAlpha2( PARTICLE_ATTRIBUTE_ALPHA2, pParticles );
  49. CM128AttributeIterator pRadius( PARTICLE_ATTRIBUTE_RADIUS, pParticles );
  50. int nParticles = pParticles->m_nActiveParticles;
  51. FourVectors EyePos;
  52. EyePos.DuplicateVector( CameraPos );
  53. FourVectors v4Fwd;
  54. if ( bCull )
  55. v4Fwd.DuplicateVector( *pCameraFwd );
  56. fltx4 fl4AlphaVis = ReplicateX4( pVisibilityData->m_flAlphaVisibility );
  57. fltx4 fl4RadVis = ReplicateX4( pVisibilityData->m_flRadiusVisibility );
  58. // indexing. We will generate the index as float and use magicf2i to convert to integer
  59. fltx4 fl4OutIdx = g_SIMD_0123; // 0 1 2 3
  60. fl4OutIdx = AddSIMD( fl4OutIdx, Four_2ToThe23s); // fix as int
  61. bool bUseVis = pVisibilityData->m_bUseVisibility;
  62. fltx4 fl4AlphaScale = ReplicateX4( 255.0 );
  63. fltx4 fl4SortKey = Four_Zeros;
  64. do
  65. {
  66. fltx4 fl4FinalAlpha = MulSIMD( *pAlpha, *pAlpha2 );
  67. fltx4 fl4FinalRadius = *pRadius;
  68. if ( bUseVis )
  69. {
  70. fl4FinalAlpha = MaxSIMD ( Four_Zeros, MinSIMD( Four_Ones, MulSIMD( fl4FinalAlpha, fl4AlphaVis) ) );
  71. fl4FinalRadius = MulSIMD( fl4FinalRadius, fl4RadVis );
  72. }
  73. // convert float 0..1 to int 0..255
  74. fl4FinalAlpha = AddSIMD( MulSIMD( fl4FinalAlpha, fl4AlphaScale ), Four_2ToThe23s );
  75. if ( eSortKeyMode == SORT_KEY_CREATION_TIME )
  76. {
  77. fl4SortKey = *pCreationTimeStamp;
  78. }
  79. if ( bCull || ( eSortKeyMode == SORT_KEY_DISTANCE ) )
  80. {
  81. fltx4 fl4X = pXYZ->x;
  82. fltx4 fl4Y = pXYZ->y;
  83. fltx4 fl4Z = pXYZ->z;
  84. fltx4 Xdiff = SubSIMD( fl4X, EyePos.x );
  85. fltx4 Ydiff = SubSIMD( fl4Y, EyePos.y );
  86. fltx4 Zdiff = SubSIMD( fl4Z, EyePos.z );
  87. if ( bCull )
  88. {
  89. fltx4 dot = AddSIMD( MulSIMD( Xdiff, v4Fwd.x ),
  90. AddSIMD(
  91. MulSIMD( Ydiff, v4Fwd.y ),
  92. MulSIMD( Zdiff, v4Fwd.z ) ) );
  93. fl4FinalAlpha = AndSIMD( fl4FinalAlpha, CmpGeSIMD( dot, Four_Zeros ) );
  94. }
  95. if ( eSortKeyMode == SORT_KEY_DISTANCE )
  96. {
  97. fl4SortKey = AddSIMD( MulSIMD( Xdiff, Xdiff ),
  98. AddSIMD( MulSIMD( Ydiff, Ydiff ),
  99. MulSIMD( Zdiff, Zdiff ) ) );
  100. }
  101. }
  102. // now, we will use simd transpose to write the output
  103. fltx4 i4Indices = AndSIMD( fl4OutIdx, LoadAlignedSIMD( (float *) g_SIMD_Low16BitsMask ) );
  104. TransposeSIMD( fl4SortKey, i4Indices, fl4FinalRadius, fl4FinalAlpha );
  105. pOutUnSorted[0] = fl4SortKey;
  106. pOutUnSorted[1] = i4Indices;
  107. pOutUnSorted[2] = fl4FinalRadius;
  108. pOutUnSorted[3] = fl4FinalAlpha;
  109. pOutUnSorted += 4;
  110. fl4OutIdx = AddSIMD( fl4OutIdx, Four_Fours );
  111. nParticles -= 4;
  112. ++pXYZ;
  113. ++pAlpha;
  114. ++pAlpha2;
  115. ++pRadius;
  116. } while( nParticles > 0 ); // we're not called with 0
  117. }
  118. #define TREATASINT(x) ( *( ( (int32 const *)( &(x) ) ) ) )
  119. static bool SortLessFunc( const ParticleRenderData_t &left, const ParticleRenderData_t &right )
  120. {
  121. return TREATASINT( left.m_flSortKey ) < TREATASINT( right.m_flSortKey );
  122. }
  123. int CParticleCollection::GenerateSortedIndexList( ParticleRenderData_t *pOut, Vector vecCamera, CParticleVisibilityData *pVisibilityData, bool bSorted )
  124. {
  125. VPROF_BUDGET( "CParticleCollection::GenerateSortedIndexList", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  126. int nParticles = m_nActiveParticles;
  127. if ( bSorted )
  128. {
  129. s_GenerateData<SORT_KEY_DISTANCE, false>( pOut, vecCamera, NULL, pVisibilityData, this );
  130. }
  131. else
  132. s_GenerateData<SORT_KEY_NONE, false>( pOut, vecCamera, NULL, pVisibilityData, this );
  133. if ( bSorted )
  134. {
  135. // sort the output in place
  136. std::make_heap( pOut, pOut + nParticles, SortLessFunc );
  137. std::sort_heap( pOut, pOut + nParticles, SortLessFunc );
  138. }
  139. return nParticles;
  140. }
  141. int CParticleCollection::GenerateCulledSortedIndexList(
  142. ParticleRenderData_t *pOut, Vector vecCamera, Vector vecFwd, CParticleVisibilityData *pVisibilityData, bool bSorted )
  143. {
  144. VPROF_BUDGET( "CParticleCollection::GenerateSortedIndexList", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
  145. int nParticles = m_nActiveParticles;
  146. if ( bSorted )
  147. {
  148. s_GenerateData<SORT_KEY_DISTANCE, true>( pOut, vecCamera, &vecFwd, pVisibilityData, this );
  149. }
  150. else
  151. s_GenerateData<SORT_KEY_NONE, true>( pOut, vecCamera, &vecFwd, pVisibilityData, this );
  152. #ifndef SWDS
  153. if ( bSorted )
  154. {
  155. // sort the output in place
  156. std::make_heap( pOut, pOut + nParticles, SortLessFunc );
  157. std::sort_heap( pOut, pOut + nParticles, SortLessFunc );
  158. }
  159. #endif
  160. return nParticles;
  161. }
  162. const ParticleRenderData_t *CParticleCollection::GetRenderList( IMatRenderContext *pRenderContext,
  163. bool bSorted, int *pNparticles,
  164. CParticleVisibilityData *pVisibilityData)
  165. {
  166. if ( bSorted )
  167. bSorted = m_pDef->m_bShouldSort;
  168. Vector vecCamera;
  169. pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
  170. ParticleRenderData_t *pOut = ( ParticleRenderData_t * ) s_SortBuffer;
  171. // check if the camera is inside the bounding box to see whether culling is worth it
  172. int nParticles;
  173. if ( vecCamera.WithinAABox( m_MinBounds, m_MaxBounds ) )
  174. {
  175. Vector vecFwd, vecRight, vecUp;
  176. pRenderContext->GetWorldSpaceCameraVectors( &vecFwd, &vecRight, &vecUp );
  177. nParticles = GenerateCulledSortedIndexList( pOut,
  178. vecCamera, vecFwd,
  179. pVisibilityData, bSorted );
  180. }
  181. else
  182. {
  183. // outside the bounds. don't bother agressive culling
  184. nParticles = GenerateSortedIndexList( pOut, vecCamera, pVisibilityData, bSorted );
  185. }
  186. *pNparticles = nParticles;
  187. return pOut + nParticles;
  188. }
  189. template<EParticleSortKeyType eSortKeyMode, bool bCull, bool bLerpCoords, class OutType_t, bool bDoColor2, bool bDoNormalVector, class VECTORITERATOR, class SCALARITERATOR>
  190. void GenerateExtendedData(
  191. void *pOutbuf, ParticleFullRenderData_Scalar_View **pIndexBuffer,
  192. Vector CameraPos, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles,
  193. float flInterpT )
  194. {
  195. OutType_t * RESTRICT pOutUnSorted = reinterpret_cast<OutType_t*>( pOutbuf );
  196. // interpolated values
  197. VECTORITERATOR pXYZ( PARTICLE_ATTRIBUTE_XYZ, pParticles );
  198. VECTORITERATOR pRGB( PARTICLE_ATTRIBUTE_TINT_RGB, pParticles );
  199. VECTORITERATOR pRGB2;
  200. SCALARITERATOR pAlpha( PARTICLE_ATTRIBUTE_ALPHA, pParticles );
  201. SCALARITERATOR pAlpha2( PARTICLE_ATTRIBUTE_ALPHA2, pParticles );
  202. SCALARITERATOR pRadius( PARTICLE_ATTRIBUTE_RADIUS, pParticles );
  203. SCALARITERATOR pRot( PARTICLE_ATTRIBUTE_ROTATION, pParticles );
  204. SCALARITERATOR pYaw( PARTICLE_ATTRIBUTE_YAW, pParticles );
  205. SCALARITERATOR pGlowAlpha;
  206. // non-interpolated values
  207. CM128AttributeIterator pSeq( PARTICLE_ATTRIBUTE_SEQUENCE_NUMBER, pParticles );
  208. CM128AttributeIterator pSeq1( PARTICLE_ATTRIBUTE_SEQUENCE_NUMBER1, pParticles );
  209. CM128AttributeIterator pCreationTimeStamp( PARTICLE_ATTRIBUTE_CREATION_TIME, pParticles );
  210. if ( bDoColor2 )
  211. {
  212. pGlowAlpha.Init( PARTICLE_ATTRIBUTE_GLOW_ALPHA, pParticles );
  213. pRGB2.Init( PARTICLE_ATTRIBUTE_GLOW_RGB, pParticles );
  214. }
  215. C4VAttributeIterator pNormal;
  216. if ( bDoNormalVector )
  217. {
  218. pNormal.Init( PARTICLE_ATTRIBUTE_NORMAL, pParticles );
  219. }
  220. int nParticles = pParticles->m_nActiveParticles;
  221. fltx4 fl4CurTime;
  222. fltx4 fl4MaximumCreationTimeToDraw = Four_2ToThe23s;
  223. if ( bLerpCoords )
  224. {
  225. fl4CurTime = ReplicateX4( pParticles->m_flTargetDrawTime );
  226. fl4MaximumCreationTimeToDraw = ReplicateX4( pParticles->m_flPrevSimTime );
  227. }
  228. else
  229. {
  230. fl4CurTime = pParticles->m_fl4CurTime;
  231. }
  232. fltx4 Four_256s = ReplicateX4( 256.0 );
  233. fltx4 fl4T = ReplicateX4( flInterpT );
  234. FourVectors EyePos;
  235. EyePos.DuplicateVector( CameraPos );
  236. FourVectors v4Fwd;
  237. if ( bCull )
  238. v4Fwd.DuplicateVector( *pCameraFwd );
  239. fltx4 fl4AlphaVis = ReplicateX4( pVisibilityData->m_flAlphaVisibility );
  240. fltx4 fl4RadVis = ReplicateX4( pVisibilityData->m_flRadiusVisibility );
  241. bool bUseVis = pVisibilityData->m_bUseVisibility;
  242. fltx4 fl4AlphaScale = ReplicateX4( 255.0 );
  243. uint8 **pOutPtrs = reinterpret_cast<uint8 **>( pIndexBuffer );
  244. do
  245. {
  246. // Note: UNDER NO CIRCUMSTANCES should you write through these
  247. // pointers inside the scope of this function! pOutUnSorted is
  248. // marked as __restrict, meaning that we have promised the compiler
  249. // that it is unaliased. Therefore any writes through an alias
  250. // will cause DOOM.
  251. pOutPtrs[0] = reinterpret_cast<uint8 *>( pOutUnSorted );
  252. pOutPtrs[1] = reinterpret_cast<uint8 *>( pOutUnSorted ) + sizeof( float );
  253. pOutPtrs[2] = reinterpret_cast<uint8 *>( pOutUnSorted ) + 2 * sizeof( float );
  254. pOutPtrs[3] = reinterpret_cast<uint8 *>( pOutUnSorted ) + 3 * sizeof( float );
  255. fltx4 fl4FinalAlpha = MulSIMD( pAlpha( fl4T ), pAlpha2( fl4T ) );
  256. fltx4 fl4FinalRadius = pRadius( fl4T );
  257. if ( bUseVis )
  258. {
  259. fl4FinalAlpha = MaxSIMD ( Four_Zeros, MinSIMD( Four_Ones, MulSIMD( fl4FinalAlpha, fl4AlphaVis) ) );
  260. fl4FinalRadius = MulSIMD( fl4FinalRadius, fl4RadVis );
  261. }
  262. // convert float 0..1 to int 0..255
  263. fl4FinalAlpha = AddSIMD( MulSIMD( fl4FinalAlpha, fl4AlphaScale ), Four_2ToThe23s );
  264. fltx4 fl4X = pXYZ.X( fl4T );
  265. fltx4 fl4Y = pXYZ.Y( fl4T );
  266. fltx4 fl4Z = pXYZ.Z( fl4T );
  267. if ( eSortKeyMode == SORT_KEY_CREATION_TIME )
  268. {
  269. pOutUnSorted->m_fl4SortKey = *pCreationTimeStamp;
  270. }
  271. if ( bCull || ( eSortKeyMode == SORT_KEY_DISTANCE ) )
  272. {
  273. fltx4 Xdiff = SubSIMD( fl4X, EyePos.x );
  274. fltx4 Ydiff = SubSIMD( fl4Y, EyePos.y );
  275. fltx4 Zdiff = SubSIMD( fl4Z, EyePos.z );
  276. if ( bCull )
  277. {
  278. fltx4 dot = AddSIMD( MulSIMD( Xdiff, v4Fwd.x ),
  279. AddSIMD(
  280. MulSIMD( Ydiff, v4Fwd.y ),
  281. MulSIMD( Zdiff, v4Fwd.z ) ) );
  282. fl4FinalAlpha = AndSIMD( fl4FinalAlpha, CmpGeSIMD( dot, Four_Zeros ) );
  283. }
  284. if ( eSortKeyMode == SORT_KEY_DISTANCE )
  285. {
  286. pOutUnSorted->m_fl4SortKey = AddSIMD( MulSIMD( Xdiff, Xdiff ),
  287. AddSIMD( MulSIMD( Ydiff, Ydiff ),
  288. MulSIMD( Zdiff, Zdiff ) ) );
  289. }
  290. }
  291. fltx4 fl4Age = SubSIMD( fl4CurTime, *pCreationTimeStamp );
  292. // if we are lerping, we need to supress particles which didn't exist on the last sim
  293. if ( bLerpCoords )
  294. {
  295. fl4FinalAlpha = AndSIMD( fl4FinalAlpha, CmpLtSIMD( *pCreationTimeStamp, fl4MaximumCreationTimeToDraw ) );
  296. }
  297. pOutUnSorted->m_fl4XYZ.x = fl4X;
  298. pOutUnSorted->m_fl4XYZ.y = fl4Y;
  299. pOutUnSorted->m_fl4XYZ.z = fl4Z;
  300. pOutUnSorted->m_fl4Alpha = fl4FinalAlpha;
  301. pOutUnSorted->m_fl4Red = AddSIMD( MulSIMD( pRGB.X( fl4T ), fl4AlphaScale ), Four_2ToThe23s );
  302. pOutUnSorted->m_fl4Green = AddSIMD( MulSIMD( pRGB.Y( fl4T ), fl4AlphaScale ), Four_2ToThe23s );
  303. pOutUnSorted->m_fl4Blue = AddSIMD( MulSIMD( pRGB.Z( fl4T ), fl4AlphaScale ), Four_2ToThe23s );
  304. pOutUnSorted->m_fl4Radius = fl4FinalRadius;
  305. pOutUnSorted->m_fl4AnimationTimeValue = fl4Age;
  306. pOutUnSorted->m_fl4Rotation = pRot( fl4T );
  307. pOutUnSorted->m_fl4Yaw = pYaw( fl4T );
  308. if ( pSeq1.Stride() )
  309. {
  310. pOutUnSorted->m_fl4SequenceID = AddSIMD( AddSIMD( *pSeq, MulSIMD( Four_256s, *pSeq1 ) ), Four_2ToThe23s );
  311. }
  312. else
  313. {
  314. pOutUnSorted->m_fl4SequenceID = AddSIMD( *pSeq, Four_2ToThe23s );
  315. }
  316. if ( bDoColor2 )
  317. {
  318. pOutUnSorted->SetARGB2( pRGB2.X( fl4T ), pRGB2.Y( fl4T ), pRGB2.Z( fl4T ), *pGlowAlpha );
  319. ++pRGB2;
  320. ++pGlowAlpha;
  321. }
  322. if ( bDoNormalVector )
  323. {
  324. pOutUnSorted->SetNormal( pNormal.X( fl4T ), pNormal.Y( fl4T ), pNormal.Z( fl4T ) );
  325. ++pNormal;
  326. }
  327. pOutUnSorted++;
  328. nParticles -= 4;
  329. pOutPtrs += 4;
  330. ++pXYZ;
  331. ++pAlpha;
  332. ++pAlpha2;
  333. ++pRadius;
  334. ++pRGB;
  335. ++pYaw;
  336. ++pRot;
  337. ++pSeq;
  338. ++pSeq1;
  339. ++pCreationTimeStamp;
  340. } while( nParticles > 0 ); // we're not called with 0
  341. }
  342. template<EParticleSortKeyType eSortKeyMode, bool bCull, bool bLerpCoords, class OutType_t, bool bDoColor2,
  343. bool bDoNormalVector>
  344. void GenerateExtendedData(
  345. void *pOutbuf, ParticleFullRenderData_Scalar_View **pIndexBuffer,
  346. Vector CameraPos, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles,
  347. float flInterpT )
  348. {
  349. if ( bLerpCoords )
  350. {
  351. GenerateExtendedData<eSortKeyMode, bCull, true, OutType_t,
  352. bDoColor2, bDoNormalVector, C4VInterpolatedAttributeIterator, CM128InterpolatedAttributeIterator>(
  353. pOutbuf, pIndexBuffer, CameraPos, pCameraFwd, pVisibilityData, pParticles, flInterpT );
  354. }
  355. else
  356. {
  357. GenerateExtendedData<eSortKeyMode, bCull, false, OutType_t,
  358. bDoColor2, bDoNormalVector, C4VAttributeIterator, CM128AttributeIterator>(
  359. pOutbuf, pIndexBuffer, CameraPos, pCameraFwd, pVisibilityData, pParticles, flInterpT );
  360. }
  361. }
  362. template<bool bCull, bool bLerpCoords, class OutType_t, bool bDoColor2, bool bDoNormal>
  363. void s_GenerateExtendedData(
  364. void *pOutbuf, ParticleFullRenderData_Scalar_View **pIndexBuffer,
  365. Vector CameraPos, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles,
  366. float flInterpT, bool bSort )
  367. {
  368. if ( bSort )
  369. {
  370. GenerateExtendedData<SORT_KEY_DISTANCE, bCull, bLerpCoords, OutType_t, bDoColor2, bDoNormal>(
  371. pOutbuf, pIndexBuffer,
  372. CameraPos, pCameraFwd, pVisibilityData,
  373. pParticles, flInterpT );
  374. }
  375. else
  376. {
  377. GenerateExtendedData<SORT_KEY_NONE, bCull, bLerpCoords, OutType_t, bDoColor2, bDoNormal>(
  378. pOutbuf, pIndexBuffer,
  379. CameraPos, pCameraFwd, pVisibilityData,
  380. pParticles, flInterpT );
  381. }
  382. }
  383. static bool SortLessFuncExtended( ParticleFullRenderData_Scalar_View * const &left, const ParticleFullRenderData_Scalar_View * const &right )
  384. {
  385. return left->m_nSortKey < right->m_nSortKey;
  386. }
  387. int GenerateExtendedSortedIndexList( Vector vecCamera, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData,
  388. CParticleCollection *pParticles, bool bSorted, void *pOutBuf,
  389. ParticleFullRenderData_Scalar_View **pParticlePtrs )
  390. {
  391. // check interpolation
  392. if ( pParticles->IsUsingInterpolatedRendering() )
  393. {
  394. float t = ( pParticles->m_flTargetDrawTime - pParticles->m_flPrevSimTime ) /
  395. ( pParticles->m_flCurTime - pParticles->m_flPrevSimTime );
  396. Assert( ( t >= 0.0 ) && ( t <= 1.0 ) );
  397. s_GenerateExtendedData<false, true, ParticleFullRenderData_SIMD_View, false, false>( pOutBuf, pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, t, bSorted );
  398. }
  399. else
  400. {
  401. s_GenerateExtendedData<false, false, ParticleFullRenderData_SIMD_View, false, false>( pOutBuf, pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, 0., bSorted );
  402. }
  403. int nParticles = pParticles->m_nActiveParticles;
  404. if ( bSorted )
  405. {
  406. // sort the output in place
  407. std::make_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
  408. std::sort_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
  409. }
  410. return nParticles;
  411. }
  412. int GenerateExtendedSortedIndexListWithPerParticleGlow(
  413. Vector vecCamera, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData,
  414. CParticleCollection *pParticles, bool bSorted, void *pOutBuf,
  415. ParticleRenderDataWithOutlineInformation_Scalar_View **pParticlePtrs )
  416. {
  417. // check interpolation
  418. if ( pParticles->IsUsingInterpolatedRendering() )
  419. {
  420. float t = ( pParticles->m_flTargetDrawTime - pParticles->m_flPrevSimTime ) /
  421. ( pParticles->m_flCurTime - pParticles->m_flPrevSimTime );
  422. Assert( ( t >= 0.0 ) && ( t <= 1.0 ) );
  423. s_GenerateExtendedData<false, true, ParticleRenderDataWithOutlineInformation_SIMD_View, true, false>(
  424. pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, t, bSorted );
  425. }
  426. else
  427. {
  428. s_GenerateExtendedData<false, false, ParticleRenderDataWithOutlineInformation_SIMD_View, true, false>(
  429. pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, 0., bSorted );
  430. }
  431. int nParticles = pParticles->m_nActiveParticles;
  432. if ( bSorted )
  433. {
  434. // sort the output in place
  435. std::make_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
  436. std::sort_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
  437. }
  438. return nParticles;
  439. }
  440. int GenerateExtendedSortedIndexListWithNormals(
  441. Vector vecCamera, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData,
  442. CParticleCollection *pParticles, bool bSorted, void *pOutBuf,
  443. ParticleRenderDataWithNormal_Scalar_View **pParticlePtrs )
  444. {
  445. // check interpolation
  446. if ( pParticles->IsUsingInterpolatedRendering() )
  447. {
  448. float t = ( pParticles->m_flTargetDrawTime - pParticles->m_flPrevSimTime ) /
  449. ( pParticles->m_flCurTime - pParticles->m_flPrevSimTime );
  450. Assert( ( t >= 0.0 ) && ( t <= 1.0 ) );
  451. s_GenerateExtendedData<false, true, ParticleRenderDataWithNormal_SIMD_View, false, true>(
  452. pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, t, bSorted );
  453. }
  454. else
  455. {
  456. s_GenerateExtendedData<false, false, ParticleRenderDataWithNormal_SIMD_View, false, true>(
  457. pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, 0., bSorted );
  458. }
  459. int nParticles = pParticles->m_nActiveParticles;
  460. if ( bSorted )
  461. {
  462. // sort the output in place
  463. std::make_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
  464. std::sort_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
  465. }
  466. return nParticles;
  467. }
  468. ParticleFullRenderData_Scalar_View **GetExtendedRenderList( CParticleCollection *pParticles,
  469. IMatRenderContext *pRenderContext,
  470. bool bSorted, int *pNparticles,
  471. CParticleVisibilityData *pVisibilityData)
  472. {
  473. Assert( sizeof( ParticleFullRenderData_Scalar_View ) == sizeof( ParticleFullRenderData_SIMD_View ) );
  474. if ( bSorted )
  475. bSorted = pParticles->m_pDef->m_bShouldSort;
  476. Vector vecCamera;
  477. pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
  478. int nParticles = GenerateExtendedSortedIndexList( vecCamera, NULL, pVisibilityData, pParticles, bSorted, s_SortBuffer, s_pParticlePtrs );
  479. *pNparticles = nParticles;
  480. return s_pParticlePtrs + nParticles;
  481. }
  482. ParticleRenderDataWithOutlineInformation_Scalar_View **GetExtendedRenderListWithPerParticleGlow(
  483. CParticleCollection *pParticles,
  484. IMatRenderContext *pRenderContext,
  485. bool bSorted, int *pNparticles,
  486. CParticleVisibilityData *pVisibilityData)
  487. {
  488. Assert( sizeof( ParticleRenderDataWithOutlineInformation_Scalar_View ) == sizeof( ParticleRenderDataWithOutlineInformation_SIMD_View ) );
  489. if ( bSorted )
  490. bSorted = pParticles->m_pDef->m_bShouldSort;
  491. Vector vecCamera;
  492. pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
  493. int nParticles = GenerateExtendedSortedIndexListWithPerParticleGlow(
  494. vecCamera, NULL, pVisibilityData, pParticles, bSorted, s_SortBuffer,
  495. ( ParticleRenderDataWithOutlineInformation_Scalar_View ** ) s_pParticlePtrs );
  496. *pNparticles = nParticles;
  497. return ( ParticleRenderDataWithOutlineInformation_Scalar_View ** ) ( s_pParticlePtrs + nParticles );
  498. }
  499. ParticleRenderDataWithNormal_Scalar_View **GetExtendedRenderListWithNormals(
  500. CParticleCollection *pParticles,
  501. IMatRenderContext *pRenderContext,
  502. bool bSorted, int *pNparticles,
  503. CParticleVisibilityData *pVisibilityData)
  504. {
  505. Assert( sizeof( ParticleRenderDataWithNormal_SIMD_View ) == sizeof( ParticleRenderDataWithNormal_Scalar_View ) );
  506. if ( bSorted )
  507. bSorted = pParticles->m_pDef->m_bShouldSort;
  508. Vector vecCamera;
  509. pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
  510. int nParticles = GenerateExtendedSortedIndexListWithNormals(
  511. vecCamera, NULL, pVisibilityData, pParticles, bSorted, s_SortBuffer,
  512. ( ParticleRenderDataWithNormal_Scalar_View ** ) s_pParticlePtrs );
  513. *pNparticles = nParticles;
  514. return ( ParticleRenderDataWithNormal_Scalar_View ** ) ( s_pParticlePtrs + nParticles );
  515. }