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
606 lines
21 KiB
//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose: particle system code
|
|
//
|
|
//===========================================================================//
|
|
|
|
#include <algorithm>
|
|
#include "tier0/platform.h"
|
|
#include "tier0/vprof.h"
|
|
#include "particles/particles.h"
|
|
#include "particles_internal.h"
|
|
#include "bitmap/psheet.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
#define SORTBUFSIZE0 (( MAX_PARTICLES_IN_A_SYSTEM + 4 ) * sizeof( ParticleRenderData_t ) )
|
|
#define SORTBUFSIZE1 ( ( 1 + MAX_PARTICLES_IN_A_SYSTEM / 4 )* sizeof( ParticleFullRenderData_Scalar_View ) )
|
|
#define SORTBUFSIZE2 ( ( 1 + MAX_PARTICLES_IN_A_SYSTEM / 4 )* sizeof( ParticleRenderDataWithOutlineInformation_Scalar_View ) )
|
|
|
|
static ALIGN16 uint8 s_SortBuffer[ COMPILETIME_MAX( COMPILETIME_MAX( SORTBUFSIZE0, SORTBUFSIZE1 ), SORTBUFSIZE2 )] ALIGN16_POST;
|
|
|
|
static ALIGN16 ParticleFullRenderData_Scalar_View *s_pParticlePtrs[MAX_PARTICLES_IN_A_SYSTEM] ALIGN16_POST;
|
|
|
|
|
|
|
|
enum EParticleSortKeyType
|
|
{
|
|
SORT_KEY_NONE,
|
|
SORT_KEY_DISTANCE,
|
|
SORT_KEY_CREATION_TIME,
|
|
};
|
|
|
|
|
|
void C4VInterpolatedAttributeIterator::Init( int nAttribute, CParticleCollection *pParticles )
|
|
{
|
|
// initializing this is somewhat complicated by the behavior of prev_xyz and xyz
|
|
|
|
m_pData = pParticles->Get4VAttributePtr( nAttribute, &m_nStride );
|
|
Assert( pParticles->GetPrevAttributeMemory() );
|
|
if ( m_nStride )
|
|
{
|
|
m_nOldDataOffset =
|
|
pParticles->m_PreviousFrameAttributes.ByteAddress( nAttribute ) - pParticles->m_ParticleAttributes.ByteAddress( nAttribute );
|
|
}
|
|
else
|
|
{
|
|
// it's constant data
|
|
m_nOldDataOffset = 0;
|
|
}
|
|
}
|
|
|
|
template<EParticleSortKeyType eSortKeyMode, bool bCull> void s_GenerateData( void *pOutData, Vector CameraPos, Vector *pCameraFwd,
|
|
CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles )
|
|
{
|
|
fltx4 *pOutUnSorted = reinterpret_cast<fltx4 *>( pOutData );
|
|
|
|
C4VAttributeIterator pXYZ( PARTICLE_ATTRIBUTE_XYZ, pParticles );
|
|
CM128AttributeIterator pCreationTimeStamp( PARTICLE_ATTRIBUTE_CREATION_TIME, pParticles );
|
|
CM128AttributeIterator pAlpha( PARTICLE_ATTRIBUTE_ALPHA, pParticles );
|
|
CM128AttributeIterator pAlpha2( PARTICLE_ATTRIBUTE_ALPHA2, pParticles );
|
|
CM128AttributeIterator pRadius( PARTICLE_ATTRIBUTE_RADIUS, pParticles );
|
|
|
|
int nParticles = pParticles->m_nActiveParticles;
|
|
|
|
FourVectors EyePos;
|
|
EyePos.DuplicateVector( CameraPos );
|
|
FourVectors v4Fwd;
|
|
if ( bCull )
|
|
v4Fwd.DuplicateVector( *pCameraFwd );
|
|
|
|
|
|
fltx4 fl4AlphaVis = ReplicateX4( pVisibilityData->m_flAlphaVisibility );
|
|
fltx4 fl4RadVis = ReplicateX4( pVisibilityData->m_flRadiusVisibility );
|
|
|
|
// indexing. We will generate the index as float and use magicf2i to convert to integer
|
|
fltx4 fl4OutIdx = g_SIMD_0123; // 0 1 2 3
|
|
|
|
fl4OutIdx = AddSIMD( fl4OutIdx, Four_2ToThe23s); // fix as int
|
|
|
|
bool bUseVis = pVisibilityData->m_bUseVisibility;
|
|
|
|
fltx4 fl4AlphaScale = ReplicateX4( 255.0 );
|
|
fltx4 fl4SortKey = Four_Zeros;
|
|
|
|
do
|
|
{
|
|
fltx4 fl4FinalAlpha = MulSIMD( *pAlpha, *pAlpha2 );
|
|
fltx4 fl4FinalRadius = *pRadius;
|
|
|
|
if ( bUseVis )
|
|
{
|
|
fl4FinalAlpha = MaxSIMD ( Four_Zeros, MinSIMD( Four_Ones, MulSIMD( fl4FinalAlpha, fl4AlphaVis) ) );
|
|
fl4FinalRadius = MulSIMD( fl4FinalRadius, fl4RadVis );
|
|
}
|
|
// convert float 0..1 to int 0..255
|
|
fl4FinalAlpha = AddSIMD( MulSIMD( fl4FinalAlpha, fl4AlphaScale ), Four_2ToThe23s );
|
|
|
|
if ( eSortKeyMode == SORT_KEY_CREATION_TIME )
|
|
{
|
|
fl4SortKey = *pCreationTimeStamp;
|
|
}
|
|
if ( bCull || ( eSortKeyMode == SORT_KEY_DISTANCE ) )
|
|
{
|
|
fltx4 fl4X = pXYZ->x;
|
|
fltx4 fl4Y = pXYZ->y;
|
|
fltx4 fl4Z = pXYZ->z;
|
|
fltx4 Xdiff = SubSIMD( fl4X, EyePos.x );
|
|
fltx4 Ydiff = SubSIMD( fl4Y, EyePos.y );
|
|
fltx4 Zdiff = SubSIMD( fl4Z, EyePos.z );
|
|
if ( bCull )
|
|
{
|
|
fltx4 dot = AddSIMD( MulSIMD( Xdiff, v4Fwd.x ),
|
|
AddSIMD(
|
|
MulSIMD( Ydiff, v4Fwd.y ),
|
|
MulSIMD( Zdiff, v4Fwd.z ) ) );
|
|
fl4FinalAlpha = AndSIMD( fl4FinalAlpha, CmpGeSIMD( dot, Four_Zeros ) );
|
|
}
|
|
if ( eSortKeyMode == SORT_KEY_DISTANCE )
|
|
{
|
|
fl4SortKey = AddSIMD( MulSIMD( Xdiff, Xdiff ),
|
|
AddSIMD( MulSIMD( Ydiff, Ydiff ),
|
|
MulSIMD( Zdiff, Zdiff ) ) );
|
|
}
|
|
}
|
|
// now, we will use simd transpose to write the output
|
|
fltx4 i4Indices = AndSIMD( fl4OutIdx, LoadAlignedSIMD( (float *) g_SIMD_Low16BitsMask ) );
|
|
TransposeSIMD( fl4SortKey, i4Indices, fl4FinalRadius, fl4FinalAlpha );
|
|
pOutUnSorted[0] = fl4SortKey;
|
|
pOutUnSorted[1] = i4Indices;
|
|
pOutUnSorted[2] = fl4FinalRadius;
|
|
pOutUnSorted[3] = fl4FinalAlpha;
|
|
|
|
pOutUnSorted += 4;
|
|
|
|
fl4OutIdx = AddSIMD( fl4OutIdx, Four_Fours );
|
|
|
|
nParticles -= 4;
|
|
|
|
++pXYZ;
|
|
++pAlpha;
|
|
++pAlpha2;
|
|
++pRadius;
|
|
} while( nParticles > 0 ); // we're not called with 0
|
|
}
|
|
|
|
|
|
|
|
#define TREATASINT(x) ( *( ( (int32 const *)( &(x) ) ) ) )
|
|
|
|
static bool SortLessFunc( const ParticleRenderData_t &left, const ParticleRenderData_t &right )
|
|
{
|
|
return TREATASINT( left.m_flSortKey ) < TREATASINT( right.m_flSortKey );
|
|
|
|
}
|
|
|
|
|
|
int CParticleCollection::GenerateSortedIndexList( ParticleRenderData_t *pOut, Vector vecCamera, CParticleVisibilityData *pVisibilityData, bool bSorted )
|
|
{
|
|
VPROF_BUDGET( "CParticleCollection::GenerateSortedIndexList", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
int nParticles = m_nActiveParticles;
|
|
if ( bSorted )
|
|
{
|
|
s_GenerateData<SORT_KEY_DISTANCE, false>( pOut, vecCamera, NULL, pVisibilityData, this );
|
|
}
|
|
else
|
|
s_GenerateData<SORT_KEY_NONE, false>( pOut, vecCamera, NULL, pVisibilityData, this );
|
|
|
|
if ( bSorted )
|
|
{
|
|
// sort the output in place
|
|
std::make_heap( pOut, pOut + nParticles, SortLessFunc );
|
|
std::sort_heap( pOut, pOut + nParticles, SortLessFunc );
|
|
}
|
|
return nParticles;
|
|
}
|
|
|
|
int CParticleCollection::GenerateCulledSortedIndexList(
|
|
ParticleRenderData_t *pOut, Vector vecCamera, Vector vecFwd, CParticleVisibilityData *pVisibilityData, bool bSorted )
|
|
{
|
|
VPROF_BUDGET( "CParticleCollection::GenerateSortedIndexList", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
|
|
|
|
int nParticles = m_nActiveParticles;
|
|
if ( bSorted )
|
|
{
|
|
s_GenerateData<SORT_KEY_DISTANCE, true>( pOut, vecCamera, &vecFwd, pVisibilityData, this );
|
|
}
|
|
else
|
|
s_GenerateData<SORT_KEY_NONE, true>( pOut, vecCamera, &vecFwd, pVisibilityData, this );
|
|
|
|
#ifndef SWDS
|
|
if ( bSorted )
|
|
{
|
|
// sort the output in place
|
|
std::make_heap( pOut, pOut + nParticles, SortLessFunc );
|
|
std::sort_heap( pOut, pOut + nParticles, SortLessFunc );
|
|
}
|
|
#endif
|
|
return nParticles;
|
|
}
|
|
|
|
const ParticleRenderData_t *CParticleCollection::GetRenderList( IMatRenderContext *pRenderContext,
|
|
bool bSorted, int *pNparticles,
|
|
CParticleVisibilityData *pVisibilityData)
|
|
{
|
|
if ( bSorted )
|
|
bSorted = m_pDef->m_bShouldSort;
|
|
|
|
Vector vecCamera;
|
|
pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
|
|
ParticleRenderData_t *pOut = ( ParticleRenderData_t * ) s_SortBuffer;
|
|
// check if the camera is inside the bounding box to see whether culling is worth it
|
|
int nParticles;
|
|
|
|
if ( vecCamera.WithinAABox( m_MinBounds, m_MaxBounds ) )
|
|
{
|
|
Vector vecFwd, vecRight, vecUp;
|
|
pRenderContext->GetWorldSpaceCameraVectors( &vecFwd, &vecRight, &vecUp );
|
|
|
|
nParticles = GenerateCulledSortedIndexList( pOut,
|
|
vecCamera, vecFwd,
|
|
pVisibilityData, bSorted );
|
|
}
|
|
else
|
|
{
|
|
// outside the bounds. don't bother agressive culling
|
|
nParticles = GenerateSortedIndexList( pOut, vecCamera, pVisibilityData, bSorted );
|
|
}
|
|
*pNparticles = nParticles;
|
|
return pOut + nParticles;
|
|
}
|
|
|
|
template<EParticleSortKeyType eSortKeyMode, bool bCull, bool bLerpCoords, class OutType_t, bool bDoColor2, bool bDoNormalVector, class VECTORITERATOR, class SCALARITERATOR>
|
|
void GenerateExtendedData(
|
|
void *pOutbuf, ParticleFullRenderData_Scalar_View **pIndexBuffer,
|
|
Vector CameraPos, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles,
|
|
float flInterpT )
|
|
{
|
|
OutType_t * RESTRICT pOutUnSorted = reinterpret_cast<OutType_t*>( pOutbuf );
|
|
|
|
// interpolated values
|
|
VECTORITERATOR pXYZ( PARTICLE_ATTRIBUTE_XYZ, pParticles );
|
|
VECTORITERATOR pRGB( PARTICLE_ATTRIBUTE_TINT_RGB, pParticles );
|
|
VECTORITERATOR pRGB2;
|
|
SCALARITERATOR pAlpha( PARTICLE_ATTRIBUTE_ALPHA, pParticles );
|
|
SCALARITERATOR pAlpha2( PARTICLE_ATTRIBUTE_ALPHA2, pParticles );
|
|
SCALARITERATOR pRadius( PARTICLE_ATTRIBUTE_RADIUS, pParticles );
|
|
SCALARITERATOR pRot( PARTICLE_ATTRIBUTE_ROTATION, pParticles );
|
|
SCALARITERATOR pYaw( PARTICLE_ATTRIBUTE_YAW, pParticles );
|
|
SCALARITERATOR pGlowAlpha;
|
|
|
|
// non-interpolated values
|
|
CM128AttributeIterator pSeq( PARTICLE_ATTRIBUTE_SEQUENCE_NUMBER, pParticles );
|
|
CM128AttributeIterator pSeq1( PARTICLE_ATTRIBUTE_SEQUENCE_NUMBER1, pParticles );
|
|
CM128AttributeIterator pCreationTimeStamp( PARTICLE_ATTRIBUTE_CREATION_TIME, pParticles );
|
|
|
|
if ( bDoColor2 )
|
|
{
|
|
pGlowAlpha.Init( PARTICLE_ATTRIBUTE_GLOW_ALPHA, pParticles );
|
|
pRGB2.Init( PARTICLE_ATTRIBUTE_GLOW_RGB, pParticles );
|
|
}
|
|
|
|
C4VAttributeIterator pNormal;
|
|
if ( bDoNormalVector )
|
|
{
|
|
pNormal.Init( PARTICLE_ATTRIBUTE_NORMAL, pParticles );
|
|
}
|
|
|
|
int nParticles = pParticles->m_nActiveParticles;
|
|
fltx4 fl4CurTime;
|
|
fltx4 fl4MaximumCreationTimeToDraw = Four_2ToThe23s;
|
|
|
|
if ( bLerpCoords )
|
|
{
|
|
fl4CurTime = ReplicateX4( pParticles->m_flTargetDrawTime );
|
|
fl4MaximumCreationTimeToDraw = ReplicateX4( pParticles->m_flPrevSimTime );
|
|
}
|
|
else
|
|
{
|
|
fl4CurTime = pParticles->m_fl4CurTime;
|
|
}
|
|
fltx4 Four_256s = ReplicateX4( 256.0 );
|
|
fltx4 fl4T = ReplicateX4( flInterpT );
|
|
|
|
FourVectors EyePos;
|
|
EyePos.DuplicateVector( CameraPos );
|
|
FourVectors v4Fwd;
|
|
if ( bCull )
|
|
v4Fwd.DuplicateVector( *pCameraFwd );
|
|
|
|
|
|
fltx4 fl4AlphaVis = ReplicateX4( pVisibilityData->m_flAlphaVisibility );
|
|
fltx4 fl4RadVis = ReplicateX4( pVisibilityData->m_flRadiusVisibility );
|
|
|
|
bool bUseVis = pVisibilityData->m_bUseVisibility;
|
|
|
|
fltx4 fl4AlphaScale = ReplicateX4( 255.0 );
|
|
uint8 **pOutPtrs = reinterpret_cast<uint8 **>( pIndexBuffer );
|
|
|
|
do
|
|
{
|
|
// Note: UNDER NO CIRCUMSTANCES should you write through these
|
|
// pointers inside the scope of this function! pOutUnSorted is
|
|
// marked as __restrict, meaning that we have promised the compiler
|
|
// that it is unaliased. Therefore any writes through an alias
|
|
// will cause DOOM.
|
|
pOutPtrs[0] = reinterpret_cast<uint8 *>( pOutUnSorted );
|
|
pOutPtrs[1] = reinterpret_cast<uint8 *>( pOutUnSorted ) + sizeof( float );
|
|
pOutPtrs[2] = reinterpret_cast<uint8 *>( pOutUnSorted ) + 2 * sizeof( float );
|
|
pOutPtrs[3] = reinterpret_cast<uint8 *>( pOutUnSorted ) + 3 * sizeof( float );
|
|
|
|
|
|
fltx4 fl4FinalAlpha = MulSIMD( pAlpha( fl4T ), pAlpha2( fl4T ) );
|
|
fltx4 fl4FinalRadius = pRadius( fl4T );
|
|
|
|
if ( bUseVis )
|
|
{
|
|
fl4FinalAlpha = MaxSIMD ( Four_Zeros, MinSIMD( Four_Ones, MulSIMD( fl4FinalAlpha, fl4AlphaVis) ) );
|
|
fl4FinalRadius = MulSIMD( fl4FinalRadius, fl4RadVis );
|
|
}
|
|
// convert float 0..1 to int 0..255
|
|
fl4FinalAlpha = AddSIMD( MulSIMD( fl4FinalAlpha, fl4AlphaScale ), Four_2ToThe23s );
|
|
|
|
fltx4 fl4X = pXYZ.X( fl4T );
|
|
fltx4 fl4Y = pXYZ.Y( fl4T );
|
|
fltx4 fl4Z = pXYZ.Z( fl4T );
|
|
if ( eSortKeyMode == SORT_KEY_CREATION_TIME )
|
|
{
|
|
pOutUnSorted->m_fl4SortKey = *pCreationTimeStamp;
|
|
}
|
|
if ( bCull || ( eSortKeyMode == SORT_KEY_DISTANCE ) )
|
|
{
|
|
fltx4 Xdiff = SubSIMD( fl4X, EyePos.x );
|
|
fltx4 Ydiff = SubSIMD( fl4Y, EyePos.y );
|
|
fltx4 Zdiff = SubSIMD( fl4Z, EyePos.z );
|
|
if ( bCull )
|
|
{
|
|
fltx4 dot = AddSIMD( MulSIMD( Xdiff, v4Fwd.x ),
|
|
AddSIMD(
|
|
MulSIMD( Ydiff, v4Fwd.y ),
|
|
MulSIMD( Zdiff, v4Fwd.z ) ) );
|
|
fl4FinalAlpha = AndSIMD( fl4FinalAlpha, CmpGeSIMD( dot, Four_Zeros ) );
|
|
}
|
|
if ( eSortKeyMode == SORT_KEY_DISTANCE )
|
|
{
|
|
pOutUnSorted->m_fl4SortKey = AddSIMD( MulSIMD( Xdiff, Xdiff ),
|
|
AddSIMD( MulSIMD( Ydiff, Ydiff ),
|
|
MulSIMD( Zdiff, Zdiff ) ) );
|
|
}
|
|
}
|
|
fltx4 fl4Age = SubSIMD( fl4CurTime, *pCreationTimeStamp );
|
|
// if we are lerping, we need to supress particles which didn't exist on the last sim
|
|
if ( bLerpCoords )
|
|
{
|
|
fl4FinalAlpha = AndSIMD( fl4FinalAlpha, CmpLtSIMD( *pCreationTimeStamp, fl4MaximumCreationTimeToDraw ) );
|
|
}
|
|
pOutUnSorted->m_fl4XYZ.x = fl4X;
|
|
pOutUnSorted->m_fl4XYZ.y = fl4Y;
|
|
pOutUnSorted->m_fl4XYZ.z = fl4Z;
|
|
pOutUnSorted->m_fl4Alpha = fl4FinalAlpha;
|
|
pOutUnSorted->m_fl4Red = AddSIMD( MulSIMD( pRGB.X( fl4T ), fl4AlphaScale ), Four_2ToThe23s );
|
|
pOutUnSorted->m_fl4Green = AddSIMD( MulSIMD( pRGB.Y( fl4T ), fl4AlphaScale ), Four_2ToThe23s );
|
|
pOutUnSorted->m_fl4Blue = AddSIMD( MulSIMD( pRGB.Z( fl4T ), fl4AlphaScale ), Four_2ToThe23s );
|
|
pOutUnSorted->m_fl4Radius = fl4FinalRadius;
|
|
pOutUnSorted->m_fl4AnimationTimeValue = fl4Age;
|
|
pOutUnSorted->m_fl4Rotation = pRot( fl4T );
|
|
pOutUnSorted->m_fl4Yaw = pYaw( fl4T );
|
|
if ( pSeq1.Stride() )
|
|
{
|
|
pOutUnSorted->m_fl4SequenceID = AddSIMD( AddSIMD( *pSeq, MulSIMD( Four_256s, *pSeq1 ) ), Four_2ToThe23s );
|
|
}
|
|
else
|
|
{
|
|
pOutUnSorted->m_fl4SequenceID = AddSIMD( *pSeq, Four_2ToThe23s );
|
|
}
|
|
|
|
if ( bDoColor2 )
|
|
{
|
|
pOutUnSorted->SetARGB2( pRGB2.X( fl4T ), pRGB2.Y( fl4T ), pRGB2.Z( fl4T ), *pGlowAlpha );
|
|
++pRGB2;
|
|
++pGlowAlpha;
|
|
}
|
|
if ( bDoNormalVector )
|
|
{
|
|
pOutUnSorted->SetNormal( pNormal.X( fl4T ), pNormal.Y( fl4T ), pNormal.Z( fl4T ) );
|
|
++pNormal;
|
|
}
|
|
|
|
|
|
pOutUnSorted++;
|
|
nParticles -= 4;
|
|
pOutPtrs += 4;
|
|
|
|
++pXYZ;
|
|
++pAlpha;
|
|
++pAlpha2;
|
|
++pRadius;
|
|
++pRGB;
|
|
++pYaw;
|
|
++pRot;
|
|
++pSeq;
|
|
++pSeq1;
|
|
++pCreationTimeStamp;
|
|
|
|
} while( nParticles > 0 ); // we're not called with 0
|
|
|
|
}
|
|
|
|
template<EParticleSortKeyType eSortKeyMode, bool bCull, bool bLerpCoords, class OutType_t, bool bDoColor2,
|
|
bool bDoNormalVector>
|
|
void GenerateExtendedData(
|
|
void *pOutbuf, ParticleFullRenderData_Scalar_View **pIndexBuffer,
|
|
Vector CameraPos, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles,
|
|
float flInterpT )
|
|
{
|
|
if ( bLerpCoords )
|
|
{
|
|
GenerateExtendedData<eSortKeyMode, bCull, true, OutType_t,
|
|
bDoColor2, bDoNormalVector, C4VInterpolatedAttributeIterator, CM128InterpolatedAttributeIterator>(
|
|
pOutbuf, pIndexBuffer, CameraPos, pCameraFwd, pVisibilityData, pParticles, flInterpT );
|
|
|
|
}
|
|
else
|
|
{
|
|
GenerateExtendedData<eSortKeyMode, bCull, false, OutType_t,
|
|
bDoColor2, bDoNormalVector, C4VAttributeIterator, CM128AttributeIterator>(
|
|
pOutbuf, pIndexBuffer, CameraPos, pCameraFwd, pVisibilityData, pParticles, flInterpT );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
template<bool bCull, bool bLerpCoords, class OutType_t, bool bDoColor2, bool bDoNormal>
|
|
void s_GenerateExtendedData(
|
|
void *pOutbuf, ParticleFullRenderData_Scalar_View **pIndexBuffer,
|
|
Vector CameraPos, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData, CParticleCollection *pParticles,
|
|
float flInterpT, bool bSort )
|
|
{
|
|
if ( bSort )
|
|
{
|
|
GenerateExtendedData<SORT_KEY_DISTANCE, bCull, bLerpCoords, OutType_t, bDoColor2, bDoNormal>(
|
|
pOutbuf, pIndexBuffer,
|
|
CameraPos, pCameraFwd, pVisibilityData,
|
|
pParticles, flInterpT );
|
|
}
|
|
else
|
|
{
|
|
GenerateExtendedData<SORT_KEY_NONE, bCull, bLerpCoords, OutType_t, bDoColor2, bDoNormal>(
|
|
pOutbuf, pIndexBuffer,
|
|
CameraPos, pCameraFwd, pVisibilityData,
|
|
pParticles, flInterpT );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool SortLessFuncExtended( ParticleFullRenderData_Scalar_View * const &left, const ParticleFullRenderData_Scalar_View * const &right )
|
|
{
|
|
return left->m_nSortKey < right->m_nSortKey;
|
|
|
|
}
|
|
|
|
int GenerateExtendedSortedIndexList( Vector vecCamera, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData,
|
|
CParticleCollection *pParticles, bool bSorted, void *pOutBuf,
|
|
ParticleFullRenderData_Scalar_View **pParticlePtrs )
|
|
{
|
|
// check interpolation
|
|
if ( pParticles->IsUsingInterpolatedRendering() )
|
|
{
|
|
float t = ( pParticles->m_flTargetDrawTime - pParticles->m_flPrevSimTime ) /
|
|
( pParticles->m_flCurTime - pParticles->m_flPrevSimTime );
|
|
Assert( ( t >= 0.0 ) && ( t <= 1.0 ) );
|
|
s_GenerateExtendedData<false, true, ParticleFullRenderData_SIMD_View, false, false>( pOutBuf, pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, t, bSorted );
|
|
}
|
|
else
|
|
{
|
|
s_GenerateExtendedData<false, false, ParticleFullRenderData_SIMD_View, false, false>( pOutBuf, pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, 0., bSorted );
|
|
}
|
|
int nParticles = pParticles->m_nActiveParticles;
|
|
if ( bSorted )
|
|
{
|
|
// sort the output in place
|
|
std::make_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
|
|
std::sort_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
|
|
}
|
|
return nParticles;
|
|
}
|
|
|
|
int GenerateExtendedSortedIndexListWithPerParticleGlow(
|
|
Vector vecCamera, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData,
|
|
CParticleCollection *pParticles, bool bSorted, void *pOutBuf,
|
|
ParticleRenderDataWithOutlineInformation_Scalar_View **pParticlePtrs )
|
|
{
|
|
// check interpolation
|
|
if ( pParticles->IsUsingInterpolatedRendering() )
|
|
{
|
|
float t = ( pParticles->m_flTargetDrawTime - pParticles->m_flPrevSimTime ) /
|
|
( pParticles->m_flCurTime - pParticles->m_flPrevSimTime );
|
|
Assert( ( t >= 0.0 ) && ( t <= 1.0 ) );
|
|
s_GenerateExtendedData<false, true, ParticleRenderDataWithOutlineInformation_SIMD_View, true, false>(
|
|
pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, t, bSorted );
|
|
}
|
|
else
|
|
{
|
|
s_GenerateExtendedData<false, false, ParticleRenderDataWithOutlineInformation_SIMD_View, true, false>(
|
|
pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, 0., bSorted );
|
|
}
|
|
int nParticles = pParticles->m_nActiveParticles;
|
|
if ( bSorted )
|
|
{
|
|
// sort the output in place
|
|
std::make_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
|
|
std::sort_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
|
|
}
|
|
return nParticles;
|
|
}
|
|
|
|
int GenerateExtendedSortedIndexListWithNormals(
|
|
Vector vecCamera, Vector *pCameraFwd, CParticleVisibilityData *pVisibilityData,
|
|
CParticleCollection *pParticles, bool bSorted, void *pOutBuf,
|
|
ParticleRenderDataWithNormal_Scalar_View **pParticlePtrs )
|
|
{
|
|
// check interpolation
|
|
if ( pParticles->IsUsingInterpolatedRendering() )
|
|
{
|
|
float t = ( pParticles->m_flTargetDrawTime - pParticles->m_flPrevSimTime ) /
|
|
( pParticles->m_flCurTime - pParticles->m_flPrevSimTime );
|
|
Assert( ( t >= 0.0 ) && ( t <= 1.0 ) );
|
|
s_GenerateExtendedData<false, true, ParticleRenderDataWithNormal_SIMD_View, false, true>(
|
|
pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, t, bSorted );
|
|
}
|
|
else
|
|
{
|
|
s_GenerateExtendedData<false, false, ParticleRenderDataWithNormal_SIMD_View, false, true>(
|
|
pOutBuf, ( ParticleFullRenderData_Scalar_View **) pParticlePtrs, vecCamera, NULL, pVisibilityData, pParticles, 0., bSorted );
|
|
}
|
|
int nParticles = pParticles->m_nActiveParticles;
|
|
if ( bSorted )
|
|
{
|
|
// sort the output in place
|
|
std::make_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
|
|
std::sort_heap( pParticlePtrs, pParticlePtrs + nParticles, SortLessFuncExtended );
|
|
}
|
|
return nParticles;
|
|
}
|
|
|
|
|
|
|
|
|
|
ParticleFullRenderData_Scalar_View **GetExtendedRenderList( CParticleCollection *pParticles,
|
|
IMatRenderContext *pRenderContext,
|
|
bool bSorted, int *pNparticles,
|
|
CParticleVisibilityData *pVisibilityData)
|
|
{
|
|
Assert( sizeof( ParticleFullRenderData_Scalar_View ) == sizeof( ParticleFullRenderData_SIMD_View ) );
|
|
if ( bSorted )
|
|
bSorted = pParticles->m_pDef->m_bShouldSort;
|
|
|
|
Vector vecCamera;
|
|
pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
|
|
int nParticles = GenerateExtendedSortedIndexList( vecCamera, NULL, pVisibilityData, pParticles, bSorted, s_SortBuffer, s_pParticlePtrs );
|
|
*pNparticles = nParticles;
|
|
return s_pParticlePtrs + nParticles;
|
|
}
|
|
|
|
ParticleRenderDataWithOutlineInformation_Scalar_View **GetExtendedRenderListWithPerParticleGlow(
|
|
CParticleCollection *pParticles,
|
|
IMatRenderContext *pRenderContext,
|
|
bool bSorted, int *pNparticles,
|
|
CParticleVisibilityData *pVisibilityData)
|
|
{
|
|
Assert( sizeof( ParticleRenderDataWithOutlineInformation_Scalar_View ) == sizeof( ParticleRenderDataWithOutlineInformation_SIMD_View ) );
|
|
if ( bSorted )
|
|
bSorted = pParticles->m_pDef->m_bShouldSort;
|
|
|
|
Vector vecCamera;
|
|
pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
|
|
int nParticles = GenerateExtendedSortedIndexListWithPerParticleGlow(
|
|
vecCamera, NULL, pVisibilityData, pParticles, bSorted, s_SortBuffer,
|
|
( ParticleRenderDataWithOutlineInformation_Scalar_View ** ) s_pParticlePtrs );
|
|
*pNparticles = nParticles;
|
|
return ( ParticleRenderDataWithOutlineInformation_Scalar_View ** ) ( s_pParticlePtrs + nParticles );
|
|
}
|
|
|
|
|
|
ParticleRenderDataWithNormal_Scalar_View **GetExtendedRenderListWithNormals(
|
|
CParticleCollection *pParticles,
|
|
IMatRenderContext *pRenderContext,
|
|
bool bSorted, int *pNparticles,
|
|
CParticleVisibilityData *pVisibilityData)
|
|
{
|
|
Assert( sizeof( ParticleRenderDataWithNormal_SIMD_View ) == sizeof( ParticleRenderDataWithNormal_Scalar_View ) );
|
|
if ( bSorted )
|
|
bSorted = pParticles->m_pDef->m_bShouldSort;
|
|
|
|
Vector vecCamera;
|
|
pRenderContext->GetWorldSpaceCameraPosition( &vecCamera );
|
|
int nParticles = GenerateExtendedSortedIndexListWithNormals(
|
|
vecCamera, NULL, pVisibilityData, pParticles, bSorted, s_SortBuffer,
|
|
( ParticleRenderDataWithNormal_Scalar_View ** ) s_pParticlePtrs );
|
|
*pNparticles = nParticles;
|
|
return ( ParticleRenderDataWithNormal_Scalar_View ** ) ( s_pParticlePtrs + nParticles );
|
|
}
|