1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "particle_simple3d.h"
#include "view.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Defined in pm_math.c
float anglemod( float a );
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
CSmartPtr<CSimple3DEmitter> CSimple3DEmitter::Create( const char *pDebugName )
{
CSimple3DEmitter* pSimple3DEmitter = new CSimple3DEmitter( pDebugName );
// Do in world space
pSimple3DEmitter->m_ParticleEffect.SetEffectCameraSpace( false );
return pSimple3DEmitter;
}
void CSimple3DEmitter::SimulateParticles( CParticleSimulateIterator *pIterator )
{
Particle3D *pParticle = (Particle3D*)pIterator->GetFirst();
while ( pParticle )
{
const float timeDelta = pIterator->GetTimeDelta();
//Should this particle die?
pParticle->m_flLifeRemaining -= timeDelta;
if ( pParticle->IsDead() )
{
pIterator->RemoveParticle( pParticle );
}
else
{
// Angular rotation
pParticle->m_vAngles.x += pParticle->m_flAngSpeed * timeDelta;
pParticle->m_vAngles.y += pParticle->m_flAngSpeed * timeDelta;
pParticle->m_vAngles.z += pParticle->m_flAngSpeed * timeDelta;
//Simulate the movement with collision
trace_t trace;
m_ParticleCollision.MoveParticle( pParticle->m_Pos, pParticle->m_vecVelocity, &pParticle->m_flAngSpeed, timeDelta, &trace );
// ---------------------------------------
// Decay towards flat
// ---------------------------------------
if (pParticle->m_flAngSpeed == 0 || trace.fraction != 1.0)
{
pParticle->m_vAngles.x = anglemod(pParticle->m_vAngles.x);
if (pParticle->m_vAngles.x < 180)
{
if (fabs(pParticle->m_vAngles.x - 90) > 0.5)
{
pParticle->m_vAngles.x = 0.5*pParticle->m_vAngles.x + 46;
}
}
else
{
if (fabs(pParticle->m_vAngles.x - 270) > 0.5)
{
pParticle->m_vAngles.x = 0.5*pParticle->m_vAngles.x + 135;
}
}
pParticle->m_vAngles.y = anglemod(pParticle->m_vAngles.y);
if (fabs(pParticle->m_vAngles.y) > 0.5)
{
pParticle->m_vAngles.y = 0.5*pParticle->m_vAngles.z;
}
}
}
pParticle = (Particle3D*)pIterator->GetNext();
}
}
void CSimple3DEmitter::RenderParticles( CParticleRenderIterator *pIterator )
{
const Particle3D *pParticle = (const Particle3D *)pIterator->GetFirst();
while ( pParticle )
{
float sortKey = CurrentViewForward().Dot( CurrentViewOrigin() - pParticle->m_Pos );
// -------------------------------------------------------
// Set color based on direction towards camera
// -------------------------------------------------------
Vector color;
Vector vFaceNorm;
Vector vCameraToFace = (pParticle->m_Pos - CurrentViewOrigin());
AngleVectors(pParticle->m_vAngles,&vFaceNorm);
float flFacing = DotProduct(vCameraToFace,vFaceNorm);
if (flFacing <= 0)
{
color[0] = pParticle->m_uchFrontColor[0] / 255.0f;
color[1] = pParticle->m_uchFrontColor[1] / 255.0f;
color[2] = pParticle->m_uchFrontColor[2] / 255.0f;
}
else
{
color[0] = pParticle->m_uchBackColor[0] / 255.0f;
color[1] = pParticle->m_uchBackColor[1] / 255.0f;
color[2] = pParticle->m_uchBackColor[2] / 255.0f;
}
//Render it in world space
RenderParticle_ColorSizeAngles(
pIterator->GetParticleDraw(),
pParticle->m_Pos,
color,
pParticle->GetFadeFraction(),
pParticle->m_uchSize,
pParticle->m_vAngles);
pParticle = (const Particle3D *)pIterator->GetNext( sortKey );
}
}
|