diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/hl2/c_energy_wave.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/hl2/c_energy_wave.cpp')
| -rw-r--r-- | game/client/hl2/c_energy_wave.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/game/client/hl2/c_energy_wave.cpp b/game/client/hl2/c_energy_wave.cpp new file mode 100644 index 0000000..31d8b32 --- /dev/null +++ b/game/client/hl2/c_energy_wave.cpp @@ -0,0 +1,416 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client's energy wave +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "materialsystem/imaterialsystem.h" +#include "materialsystem/imesh.h" +#include "energy_wave_effect.h" +#include "mathlib/vmatrix.h" +#include "clienteffectprecachesystem.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +CLIENTEFFECT_REGISTER_BEGIN( PrecacheEnergyWave ) +CLIENTEFFECT_MATERIAL( "effects/energywave/energywave" ) +CLIENTEFFECT_REGISTER_END() + +//----------------------------------------------------------------------------- +// Energy Wave: +//----------------------------------------------------------------------------- + +class C_EnergyWave : public C_BaseEntity +{ +public: + DECLARE_CLASS( C_EnergyWave, C_BaseEntity ); + DECLARE_CLIENTCLASS(); + + C_EnergyWave(); + ~C_EnergyWave(); + + void PostDataUpdate( DataUpdateType_t updateType ); + int DrawModel( int flags ); + void ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity ); + void DrawWireframeModel( ); + + CEnergyWaveEffect m_EWaveEffect; + + IMaterial* m_pWireframe; + IMaterial* m_pEWaveMat; + +private: + C_EnergyWave( const C_EnergyWave & ); // not defined, not accessible + + void ComputeEWavePoints( Vector* pt, Vector* normal, float* opacity ); + void DrawEWavePoints(Vector* pt, Vector* normal, float* opacity); + +}; + + +EXTERN_RECV_TABLE(DT_BaseEntity); + +IMPLEMENT_CLIENTCLASS_DT(C_EnergyWave, DT_EWaveEffect, CEnergyWave) +END_RECV_TABLE() + + +// ---------------------------------------------------------------------------- +// Functions. +// ---------------------------------------------------------------------------- + +C_EnergyWave::C_EnergyWave() : m_EWaveEffect(NULL, NULL) +{ + m_pWireframe = materials->FindMaterial("shadertest/wireframevertexcolor", TEXTURE_GROUP_OTHER); + m_pEWaveMat = materials->FindMaterial("effects/energywave/energywave", TEXTURE_GROUP_CLIENT_EFFECTS); + m_EWaveEffect.Spawn(); +} + +C_EnergyWave::~C_EnergyWave() +{ +} + +void C_EnergyWave::PostDataUpdate( DataUpdateType_t updateType ) +{ + MarkMessageReceived(); + + // Make sure that origin points to current origin, at least + MoveToLastReceivedPosition(); +} + + + +enum +{ + NUM_SUBDIVISIONS = 21, +}; + + +static void ComputeIndices( int is, int it, int* idx ) +{ + int is0 = (is > 0) ? (is - 1) : is; + int it0 = (it > 0) ? (it - 1) : it; + int is1 = (is < EWAVE_NUM_HORIZONTAL_POINTS - 1) ? is + 1 : is; + int it1 = (it < EWAVE_NUM_HORIZONTAL_POINTS - 1) ? it + 1 : it; + int is2 = is + 2; + int it2 = it + 2; + if (is2 >= EWAVE_NUM_HORIZONTAL_POINTS) + is2 = EWAVE_NUM_HORIZONTAL_POINTS - 1; + if (it2 >= EWAVE_NUM_HORIZONTAL_POINTS) + it2 = EWAVE_NUM_HORIZONTAL_POINTS - 1; + + idx[0] = is0 + it0 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[1] = is + it0 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[2] = is1 + it0 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[3] = is2 + it0 * EWAVE_NUM_HORIZONTAL_POINTS; + + idx[4] = is0 + it * EWAVE_NUM_HORIZONTAL_POINTS; + idx[5] = is + it * EWAVE_NUM_HORIZONTAL_POINTS; + idx[6] = is1 + it * EWAVE_NUM_HORIZONTAL_POINTS; + idx[7] = is2 + it * EWAVE_NUM_HORIZONTAL_POINTS; + + idx[8] = is0 + it1 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[9] = is + it1 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[10] = is1 + it1 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[11] = is2 + it1 * EWAVE_NUM_HORIZONTAL_POINTS; + + idx[12] = is0 + it2 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[13] = is + it2 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[14] = is1 + it2 * EWAVE_NUM_HORIZONTAL_POINTS; + idx[15] = is2 + it2 * EWAVE_NUM_HORIZONTAL_POINTS; +} + +void C_EnergyWave::ComputePoint( float s, float t, Vector& pt, Vector& normal, float& opacity ) +{ + int is = (int)s; + int it = (int)t; + if( is >= EWAVE_NUM_HORIZONTAL_POINTS ) + is -= 1; + + if( it >= EWAVE_NUM_VERTICAL_POINTS ) + it -= 1; + + int idx[16]; + ComputeIndices( is, it, idx ); + + // The patch equation is: + // px = S * M * Gx * M^T * T^T + // py = S * M * Gy * M^T * T^T + // pz = S * M * Gz * M^T * T^T + // where S = [s^3 s^2 s 1], T = [t^3 t^2 t 1] + // M is the patch type matrix, in my case I'm using a catmull-rom + // G is the array of control points. rows have constant t + static VMatrix catmullRom( -0.5, 1.5, -1.5, 0.5, + 1, -2.5, 2, -0.5, + -0.5, 0, 0.5, 0, + 0, 1, 0, 0 ); + + VMatrix controlPointsX, controlPointsY, controlPointsZ, controlPointsO; + + Vector pos; + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + const Vector& v = m_EWaveEffect.GetPoint( idx[i * 4 + j] ); + + controlPointsX[j][i] = v.x; + controlPointsY[j][i] = v.y; + controlPointsZ[j][i] = v.z; + + controlPointsO[j][i] = m_EWaveEffect.ComputeOpacity( v, GetAbsOrigin() ); + } + } + + float fs = s - is; + float ft = t - it; + + VMatrix temp, mgm[4]; + MatrixTranspose( catmullRom, temp ); + MatrixMultiply( controlPointsX, temp, mgm[0] ); + MatrixMultiply( controlPointsY, temp, mgm[1] ); + MatrixMultiply( controlPointsZ, temp, mgm[2] ); + MatrixMultiply( controlPointsO, temp, mgm[3] ); + + MatrixMultiply( catmullRom, mgm[0], mgm[0] ); + MatrixMultiply( catmullRom, mgm[1], mgm[1] ); + MatrixMultiply( catmullRom, mgm[2], mgm[2] ); + MatrixMultiply( catmullRom, mgm[3], mgm[3] ); + + Vector4D svec, tvec; + float ft2 = ft * ft; + tvec[0] = ft2 * ft; tvec[1] = ft2; tvec[2] = ft; tvec[3] = 1.0f; + + float fs2 = fs * fs; + svec[0] = fs2 * fs; svec[1] = fs2; svec[2] = fs; svec[3] = 1.0f; + + Vector4D tmp; + Vector4DMultiply( mgm[0], tvec, tmp ); + pt[0] = DotProduct4D( tmp, svec ); + Vector4DMultiply( mgm[1], tvec, tmp ); + pt[1] = DotProduct4D( tmp, svec ); + Vector4DMultiply( mgm[2], tvec, tmp ); + pt[2] = DotProduct4D( tmp, svec ); + + Vector4DMultiply( mgm[3], tvec, tmp ); + opacity = DotProduct4D( tmp, svec ); + + if ((s == 0.0f) || (t == 0.0f) || + (s == (EWAVE_NUM_HORIZONTAL_POINTS-1.0f)) || (t == (EWAVE_NUM_VERTICAL_POINTS-1.0f)) ) + { + opacity = 0.0f; + } + + if ((s <= 0.3) || (t < 0.3)) + { + opacity *= 0.35f; + } + if ((s == (EWAVE_NUM_HORIZONTAL_POINTS-0.7f)) || (t == (EWAVE_NUM_VERTICAL_POINTS-0.7f)) ) + { + opacity *= 0.35f; + } + + if (opacity < 0.0f) + opacity = 0.0f; + else if (opacity > 255.0f) + opacity = 255.0f; + + // Normal computation + Vector4D dsvec, dtvec; + dsvec[0] = 3.0f * fs2; dsvec[1] = 2.0f * fs; dsvec[2] = 1.0f; dsvec[3] = 0.0f; + dtvec[0] = 3.0f * ft2; dtvec[1] = 2.0f * ft; dtvec[2] = 1.0f; dtvec[3] = 0.0f; + + Vector ds, dt; + Vector4DMultiply( mgm[0], tvec, tmp ); + ds[0] = DotProduct4D( tmp, dsvec ); + Vector4DMultiply( mgm[1], tvec, tmp ); + ds[1] = DotProduct4D( tmp, dsvec ); + Vector4DMultiply( mgm[2], tvec, tmp ); + ds[2] = DotProduct4D( tmp, dsvec ); + + Vector4DMultiply( mgm[0], dtvec, tmp ); + dt[0] = DotProduct4D( tmp, svec ); + Vector4DMultiply( mgm[1], dtvec, tmp ); + dt[1] = DotProduct4D( tmp, svec ); + Vector4DMultiply( mgm[2], dtvec, tmp ); + dt[2] = DotProduct4D( tmp, svec ); + + CrossProduct( ds, dt, normal ); + VectorNormalize( normal ); +} + +void C_EnergyWave::DrawWireframeModel( ) +{ + IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, m_pWireframe ); + + int numLines = (EWAVE_NUM_VERTICAL_POINTS - 1) * EWAVE_NUM_HORIZONTAL_POINTS + + EWAVE_NUM_VERTICAL_POINTS * (EWAVE_NUM_HORIZONTAL_POINTS - 1); + + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_LINES, numLines ); + + Vector tmp; + for (int i = 0; i < EWAVE_NUM_VERTICAL_POINTS; ++i) + { + for (int j = 0; j < EWAVE_NUM_HORIZONTAL_POINTS; ++j) + { + if ( i > 0 ) + { + meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j, i ).Base() ); + meshBuilder.Color4ub( 255, 255, 255, 128 ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j, i - 1 ).Base() ); + meshBuilder.Color4ub( 255, 255, 255, 128 ); + meshBuilder.AdvanceVertex(); + } + + if (j > 0) + { + meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j, i ).Base() ); + meshBuilder.Color4ub( 255, 255, 255, 128 ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( m_EWaveEffect.GetPoint( j - 1, i ).Base() ); + meshBuilder.Color4ub( 255, 255, 255, 128 ); + meshBuilder.AdvanceVertex(); + } + } + } + + meshBuilder.End(); + pMesh->Draw(); +} + +//----------------------------------------------------------------------------- +// Compute the ewave points using catmull-rom +//----------------------------------------------------------------------------- + +void C_EnergyWave::ComputeEWavePoints( Vector* pt, Vector* normal, float* opacity ) +{ + int i; + for ( i = 0; i < NUM_SUBDIVISIONS; ++i) + { + float t = (EWAVE_NUM_VERTICAL_POINTS -1 ) * (float)i / (float)(NUM_SUBDIVISIONS - 1); + for (int j = 0; j < NUM_SUBDIVISIONS; ++j) + { + float s = (EWAVE_NUM_HORIZONTAL_POINTS-1) * (float)j / (float)(NUM_SUBDIVISIONS - 1); + int idx = i * NUM_SUBDIVISIONS + j; + + ComputePoint( s, t, pt[idx], normal[idx], opacity[idx] ); + } + } +} + +//----------------------------------------------------------------------------- +// Draws the base ewave +//----------------------------------------------------------------------------- + +#define TRANSITION_REGION_WIDTH 0.5f + +void C_EnergyWave::DrawEWavePoints(Vector* pt, Vector* normal, float* opacity) +{ + IMesh* pMesh = materials->GetDynamicMesh( true, NULL, NULL, m_pEWaveMat ); + + int numTriangles = (NUM_SUBDIVISIONS - 1) * (NUM_SUBDIVISIONS - 1) * 2; + + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numTriangles ); + + float du = 1.0f / (float)(NUM_SUBDIVISIONS - 1); + float dv = du; + + unsigned char color[3]; + color[0] = 255; + color[1] = 255; + color[2] = 255; + + for ( int i = 0; i < NUM_SUBDIVISIONS - 1; ++i) + { + float v = i * dv; + for (int j = 0; j < NUM_SUBDIVISIONS - 1; ++j) + { + int idx = i * NUM_SUBDIVISIONS + j; + float u = j * du; + + meshBuilder.Position3fv( pt[idx].Base() ); + meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx] ); + meshBuilder.Normal3fv( normal[idx].Base() ); + meshBuilder.TexCoord2f( 0, u, v ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( pt[idx + NUM_SUBDIVISIONS].Base() ); + meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+NUM_SUBDIVISIONS] ); + meshBuilder.Normal3fv( normal[idx + NUM_SUBDIVISIONS].Base() ); + meshBuilder.TexCoord2f( 0, u, v + dv ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( pt[idx + 1].Base() ); + meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+1] ); + meshBuilder.Normal3fv( normal[idx+1].Base() ); + meshBuilder.TexCoord2f( 0, u + du, v ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( pt[idx + 1].Base() ); + meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+1] ); + meshBuilder.Normal3fv( normal[idx+1].Base() ); + meshBuilder.TexCoord2f( 0, u + du, v ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( pt[idx + NUM_SUBDIVISIONS].Base() ); + meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+NUM_SUBDIVISIONS] ); + meshBuilder.Normal3fv( normal[idx + NUM_SUBDIVISIONS].Base() ); + meshBuilder.TexCoord2f( 0, u, v + dv ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Position3fv( pt[idx + NUM_SUBDIVISIONS + 1].Base() ); + meshBuilder.Color4ub( color[0], color[1], color[2], opacity[idx+NUM_SUBDIVISIONS+1] ); + meshBuilder.Normal3fv( normal[idx + NUM_SUBDIVISIONS + 1].Base() ); + meshBuilder.TexCoord2f( 0, u + du, v + dv ); + meshBuilder.AdvanceVertex(); + } + } + + meshBuilder.End(); + pMesh->Draw(); +} + +//----------------------------------------------------------------------------- +// Main draw entry point +//----------------------------------------------------------------------------- + +int C_EnergyWave::DrawModel( int flags ) +{ + if ( !m_bReadyToDraw ) + return 0; + + // NOTE: We've got a stiff spring case here, we need to simulate at + // a fairly fast timestep. A better solution would be to use an + // implicit method, which I'm going to not implement for the moment + + float dt = gpGlobals->frametime; + m_EWaveEffect.SetPosition( GetAbsOrigin(), GetAbsAngles() ); + m_EWaveEffect.Simulate(dt); + + Vector pt[NUM_SUBDIVISIONS * NUM_SUBDIVISIONS]; + Vector normal[NUM_SUBDIVISIONS * NUM_SUBDIVISIONS]; + float opacity[NUM_SUBDIVISIONS * NUM_SUBDIVISIONS]; + + ComputeEWavePoints( pt, normal, opacity ); + + DrawEWavePoints( pt, normal, opacity ); + + return 1; +} + + + + + |