void CGroundLine::Draw() { if ( !m_pMaterial || m_nPoints < 2 ) return; if ( !IsVisible() ) return; float flAlpha = m_Alpha; if( g_pClientMode == ClientModeCommander() ) { flAlpha = 1; // draw bright.. } CBeamSegDraw beamDraw; beamDraw.Start( m_nPoints, m_pMaterial ); for( unsigned int i=0; i < m_nPoints; i++ ) { float t = (float)i / (m_nPoints - 1); CBeamSeg seg; seg.m_vPos = m_Points[i]; VectorLerp( m_vStartColor, m_vEndColor, t, seg.m_vColor ); seg.m_flTexCoord = 0; seg.m_flWidth = m_LineWidth; seg.m_flAlpha = m_Alpha; beamDraw.NextSeg( &seg ); } beamDraw.End(); }
int C_Hairball::DrawModel( int flags ) { if ( !m_pMaterial ) return 0; CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); for ( int iHair=0; iHair < m_nHairs; iHair++ ) { CSimplePhysics::CNode *pBase = &m_Nodes[iHair * m_nNodesPerHair]; CBeamSegDraw beamDraw; beamDraw.Start( pRenderContext, m_nNodesPerHair-1, m_pMaterial ); for ( int i=0; i < m_nNodesPerHair; i++ ) { BeamSeg_t seg; seg.m_vPos = pBase[i].m_vPredicted; seg.m_vColor.Init( 0, 0, 0 ); seg.m_flTexCoord = 0; static float flHairWidth = 1; seg.m_flWidth = flHairWidth; seg.m_flAlpha = 0; beamDraw.NextSeg( &seg ); } beamDraw.End(); } return 1; }
int C_WalkerStrider::DrawModel( int flags ) { BaseClass::DrawModel( flags ); IMaterial *pMaterial = materials->FindMaterial( STRIDER_BEAM_MATERIAL, TEXTURE_GROUP_CLIENT_EFFECTS ); // hogsy start CMatRenderContextPtr pRenderContext(materials); // hogsy end Vector vGunPos; QAngle vAngles; BaseClass::GetAttachment( LookupAttachment( "BigGun" ), vGunPos, vAngles ); // Draw our beam effects. FOR_EACH_LL( m_BeamEffects, i ) { CStriderBeamEffect *pEff = &m_BeamEffects[i]; float flAlpha = (gpGlobals->curtime - pEff->m_flStartTime) / STRIDER_BEAM_LIFETIME; flAlpha = 1.0 - clamp( flAlpha, 0, 1 ); CBeamSegDraw segDraw; // hogsy start segDraw.Start(pRenderContext, 2, pMaterial); BeamSeg_t seg; // hogsy end seg.m_vColor.Init( 1, 0, 0 ); seg.m_flWidth = STRIDER_BEAM_WIDTH; seg.m_flAlpha = flAlpha; seg.m_flTexCoord = 0; seg.m_vPos = vGunPos; segDraw.NextSeg( &seg ); seg.m_flTexCoord = 1; seg.m_vPos = pEff->m_vHitPos; segDraw.NextSeg( &seg ); segDraw.End(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CSpriteTrail::DrawModel( int flags ) { VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); // Must have at least one point if ( m_nStepCount < 1 ) return 1; //See if we should draw if ( !IsVisible() || ( m_bReadyToDraw == false ) ) return 0; CEngineSprite *pSprite = Draw_SetSpriteTexture( GetModel(), m_flFrame, GetRenderMode() ); if ( pSprite == NULL ) return 0; // Specify all the segments. CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); CBeamSegDraw segDraw; segDraw.Start( pRenderContext, m_nStepCount + 1, pSprite->GetMaterial() ); // Setup the first point, always emanating from the attachment point TrailPoint_t *pLast = GetTrailPoint( m_nStepCount-1 ); TrailPoint_t currentPoint; currentPoint.m_flDieTime = gpGlobals->curtime + m_flLifeTime; ComputeScreenPosition( ¤tPoint.m_vecScreenPos ); currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos) * m_flTextureRes; currentPoint.m_flWidthVariance = 0.0f; #if SCREEN_SPACE_TRAILS VMatrix viewMatrix; materials->GetMatrix( MATERIAL_VIEW, &viewMatrix ); viewMatrix = viewMatrix.InverseTR(); #endif TrailPoint_t *pPrevPoint = NULL; float flTailAlphaDist = m_flMinFadeLength; for ( int i = 0; i <= m_nStepCount; ++i ) { // This makes it so that we're always drawing to the current location TrailPoint_t *pPoint = (i != m_nStepCount) ? GetTrailPoint(i) : ¤tPoint; float flLifePerc = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime; flLifePerc = clamp( flLifePerc, 0.0f, 1.0f ); BeamSeg_t curSeg; curSeg.m_vColor.x = (float) m_clrRender->r / 255.0f; curSeg.m_vColor.y = (float) m_clrRender->g / 255.0f; curSeg.m_vColor.z = (float) m_clrRender->b / 255.0f; float flAlphaFade = flLifePerc; if ( flTailAlphaDist > 0.0f ) { if ( pPrevPoint ) { float flDist = pPoint->m_vecScreenPos.DistTo( pPrevPoint->m_vecScreenPos ); flTailAlphaDist -= flDist; } if ( flTailAlphaDist > 0.0f ) { float flTailFade = Lerp( (m_flMinFadeLength - flTailAlphaDist) / m_flMinFadeLength, 0.0f, 1.0f ); if ( flTailFade < flAlphaFade ) { flAlphaFade = flTailFade; } } } curSeg.m_flAlpha = ( (float) GetRenderBrightness() / 255.0f ) * flAlphaFade; #if SCREEN_SPACE_TRAILS curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos; #else curSeg.m_vPos = pPoint->m_vecScreenPos; #endif if ( m_flEndWidth >= 0.0f ) { curSeg.m_flWidth = Lerp( flLifePerc, m_flEndWidth.Get(), m_flStartWidth.Get() ); } else { curSeg.m_flWidth = m_flStartWidth.Get(); } curSeg.m_flWidth += pPoint->m_flWidthVariance; if ( curSeg.m_flWidth < 0.0f ) { curSeg.m_flWidth = 0.0f; } curSeg.m_flTexCoord = pPoint->m_flTexCoord; segDraw.NextSeg( &curSeg ); // See if we're done with this bad boy if ( pPoint->m_flDieTime <= gpGlobals->curtime ) { // Push this back onto the top for use ++m_nFirstStep; --i; --m_nStepCount; } pPrevPoint = pPoint; } segDraw.End(); return 1; }
//----------------------------------------------------------------------------- // Purpose: // Input : fTimeDelta - //----------------------------------------------------------------------------- void C_ExtinguisherJet::Update( float fTimeDelta ) { if ( m_bEmit == false ) return; C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); if ( m_bUseMuzzlePoint ) { C_BaseViewModel *vm = player ? player->GetViewModel( 0 ) : NULL; if ( vm ) { int iAttachment = vm->LookupAttachment( "muzzle" ); Vector origin; QAngle angles; vm->GetAttachment( iAttachment, origin, angles ); Assert( !GetMoveParent() ); SetLocalOrigin( origin ); SetLocalAngles( angles ); } } trace_t tr; Vector shotDir, vRight, vUp; AngleVectors( GetAbsAngles(), &shotDir, &vRight, &vUp ); //FIXME: Muzzle point is incorrect on the model! if ( m_bUseMuzzlePoint ) { shotDir.Negate(); } Vector endPoint = GetAbsOrigin() + ( shotDir * 150.0f ); UTIL_TraceLine( GetAbsOrigin(), endPoint, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &tr ); bool hitWall = ( tr.fraction < 1.0f ); //Add normal jet if ( m_pEmitter.IsValid() ) { SimpleParticle *pParticle; m_pEmitter->SetSortOrigin( GetAbsOrigin() ); float tempDelta = fTimeDelta; //FIXME: All particles need to be within this loop while( m_ParticleSpawn.NextEvent( tempDelta ) ) { pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() ); if ( pParticle ) { pParticle->m_flDieTime = 0.2f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f ); pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = random->RandomInt( 32, 48 ); pParticle->m_uchStartAlpha = random->RandomInt( 128, 164 ); pParticle->m_uchEndAlpha = 0; int cScale = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector dir; QAngle ofsAngles; ofsAngles.Random( -8.0f, 8.0f ); ofsAngles += GetAbsAngles(); AngleVectors( ofsAngles, &dir ); if ( m_bUseMuzzlePoint ) { dir.Negate(); } pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 ); } //Add muzzle effect pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, GetAbsOrigin() ); if ( pParticle ) { pParticle->m_flDieTime = 0.1f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -4.0f, 4.0f ); pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = random->RandomInt( 8, 16 ); pParticle->m_uchStartAlpha = random->RandomInt( 128, 255 ); pParticle->m_uchEndAlpha = 0; int cScale = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector dir; QAngle ofsAngles; ofsAngles.Random( -64.0f, 64.0f ); ofsAngles += GetAbsAngles(); AngleVectors( ofsAngles, &dir ); if ( m_bUseMuzzlePoint ) { dir.Negate(); } pParticle->m_vecVelocity = dir * random->RandomInt( 32, 64 ); } //Add a wall effect if needed if ( hitWall ) { AddExtinguisherDecal( tr ); Vector offDir; offDir.Random( -16.0f, 16.0f ); pParticle = (SimpleParticle *) m_pEmitter->AddParticle( sizeof(SimpleParticle), m_MaterialHandle, ( tr.endpos + ( tr.plane.normal * 8.0f ) ) + offDir ); if ( pParticle ) { pParticle->m_flDieTime = 0.4f; pParticle->m_flLifetime = 0.0f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta= random->RandomFloat( -2.0f, 2.0f ); pParticle->m_uchStartSize = random->RandomInt( 8, 16 ); pParticle->m_uchEndSize = random->RandomInt( 24, 32 ); pParticle->m_uchStartAlpha = random->RandomInt( 64, 128 ); pParticle->m_uchEndAlpha = 0; int cScale = random->RandomInt( 192, 255 ); pParticle->m_uchColor[0] = cScale; pParticle->m_uchColor[1] = cScale; pParticle->m_uchColor[2] = cScale; Vector rDir; rDir = tr.plane.normal; rDir[0] += random->RandomFloat( -0.9f, 0.9f ); rDir[1] += random->RandomFloat( -0.9f, 0.9f ); rDir[2] += random->RandomFloat( -0.9f, 0.9f ); pParticle->m_vecVelocity = rDir * random->RandomInt( 32, 64 ); } } //Add small ember-like particles if ( random->RandomInt( 0, 1 ) == 0 ) { m_pEmberEmitter->SetSortOrigin( GetAbsOrigin() ); pParticle = (SimpleParticle *) m_pEmberEmitter->AddParticle( sizeof(SimpleParticle), m_pEmberEmitter->GetPMaterial( "particle/particle_smokegrenade" ), GetAbsOrigin() ); assert(pParticle); if ( pParticle ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 1.0f; pParticle->m_flRoll = 0; pParticle->m_flRollDelta = 0; pParticle->m_uchColor[0] = 255; pParticle->m_uchColor[1] = 255; pParticle->m_uchColor[2] = 255; pParticle->m_uchStartAlpha = 255; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = 1; pParticle->m_uchEndSize = 0; Vector dir; QAngle ofsAngles; ofsAngles.Random( -8.0f, 8.0f ); ofsAngles += GetAbsAngles(); AngleVectors( ofsAngles, &dir ); if ( m_bUseMuzzlePoint ) { dir.Negate(); } pParticle->m_vecVelocity = dir * random->RandomInt( 400, 800 ); } } } } // Inner beam CBeamSegDraw beamDraw; CBeamSeg seg; const int numPoints = 4; Vector beamPoints[numPoints]; beamPoints[0] = GetAbsOrigin(); // Create our beam points int i; for ( i = 0; i < numPoints; i++ ) { beamPoints[i] = GetAbsOrigin() + ( shotDir * (32*i*i) ); beamPoints[i] += vRight * sin( gpGlobals->curtime * 4.0f ) * (2.0f*i); beamPoints[i] += vUp * sin( gpGlobals->curtime * 8.0f ) * (1.0f*i); beamPoints[i] += shotDir * sin( gpGlobals->curtime * (16.0f*i) ) * (1.0f*i); } IMaterial *pMat = materials->FindMaterial( "particle/particle_smokegrenade", NULL ); beamDraw.Start( numPoints, pMat ); //Setup and draw those points for( i = 0; i < numPoints; i++ ) { float t = (float) i / (numPoints - 1); float color = 1.0f * (1.0f - t); seg.m_vColor = Vector( color, color, color ); seg.m_vPos = beamPoints[i]; seg.m_flTexCoord = (float)i/(float)(numPoints-1) - ((gpGlobals->curtime - (int)gpGlobals->curtime) * 4.0f ); seg.m_flWidth = 4.0f + ( (64.0f*t) * (fabs( sin( gpGlobals->curtime * 16.0f ) )) ); seg.m_flAlpha = color; beamDraw.NextSeg( &seg ); } beamDraw.End(); }
void AddCoolLine( const Vector &v1, const Vector &v2, unsigned long iExtraFadeOffset, bool bNegateMovementDir ) { float flLineSectionLength = 3; // How many inches each line travels. Each line is a solid color and alpha. int nLineSectionsToFade = 2; // How many lines to fade from translucent to opaque. int baseColor[3] = { 216, 183, 67 }; // gold float flTimeBetweenUpdates = 0.2f; unsigned long iLineFadeOffset = iExtraFadeOffset + (int)(gpGlobals->curtime / flTimeBetweenUpdates); if ( bNegateMovementDir ) iLineFadeOffset = 0xFFFFFFFF - iLineFadeOffset; Vector vDelta = v2 - v1; float flLineLen = vDelta.Length(); vDelta /= flLineLen; int nMaxLines = (int)(flLineLen / flLineSectionLength) + 1; static IMaterial *pWireframeMaterial = NULL; if ( !pWireframeMaterial ) pWireframeMaterial = materials->FindMaterial( "debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER ); static IMaterial *pBeamMaterial = NULL; if ( !pBeamMaterial ) pBeamMaterial = materials->FindMaterial( "effects/laser1", TEXTURE_GROUP_OTHER ); CMatRenderContextPtr pRenderContext( materials ); // Draw the solid underlying lines. IMesh* pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pWireframeMaterial ); CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_LINES, 1 ); meshBuilder.Position3fv( v1.Base() ); meshBuilder.Color4ub( baseColor[0], baseColor[1], baseColor[2], 255 ); meshBuilder.AdvanceVertex(); meshBuilder.Position3fv( v2.Base() ); meshBuilder.Color4ub( baseColor[0], baseColor[1], baseColor[2], 255 ); meshBuilder.AdvanceVertex(); meshBuilder.End( false, true ); // Draw the additive beams. float flCurDist = 0; Vector vStartPos = v1; for ( int i=0; i < nMaxLines; i++ ) { float flEndDist = MIN( flCurDist + flLineSectionLength, flLineLen ); Vector vEndPos = v1 + vDelta * flEndDist; int alpha; int iFadeAmt = (iLineFadeOffset+i) % (nLineSectionsToFade * 2); if ( iFadeAmt < nLineSectionsToFade ) alpha = (iFadeAmt * 255) / nLineSectionsToFade; else alpha = (255 * (nLineSectionsToFade - (iFadeAmt - nLineSectionsToFade))) / nLineSectionsToFade; float flAlpha = Bias( alpha / 255.0f, 0.6 ); CBeamSegDraw beamDraw; beamDraw.Start( pRenderContext, 2, pBeamMaterial ); BeamSeg_t beamSeg; beamSeg.SetColor( baseColor[0] * flAlpha / 255.0f, baseColor[1] * flAlpha / 255.0f, baseColor[2] * flAlpha / 255.0f, 1.0f ); beamSeg.m_flTexCoord = 0; beamSeg.m_flWidth = 6; beamSeg.m_vPos = vStartPos; beamDraw.NextSeg( &beamSeg ); beamSeg.m_vPos = vEndPos; beamDraw.NextSeg( &beamSeg ); beamDraw.End(); flCurDist = flEndDist; vStartPos = vEndPos; } }
//----------------------------------------------------------------------------- // Purpose: // Input : noise_divisions - // *prgNoise - // *spritemodel - // frame - // rendermode - // source - // delta - // flags - // *color - // fadescale - //----------------------------------------------------------------------------- void DrawSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel, float frame, int rendermode, const Vector& source, const Vector& delta, float startWidth, float endWidth, float scale, float freq, float speed, int segments, int flags, float* color, float fadeLength, float flHDRColorScale ) { int i, noiseIndex, noiseStep; float div, length, fraction, factor, vLast, vStep, brightness; Assert( fadeLength >= 0.0f ); CEngineSprite *pSprite = Draw_SetSpriteTexture( spritemodel, frame, rendermode ); if ( !pSprite ) return; if ( segments < 2 ) return; IMaterial *pMaterial = pSprite->GetMaterial( (RenderMode_t)rendermode ); if( pMaterial ) { static unsigned int nHDRColorScaleCache = 0; IMaterialVar *pHDRColorScaleVar = pMaterial->FindVarFast( "$hdrcolorscale", &nHDRColorScaleCache ); if( pHDRColorScaleVar ) { pHDRColorScaleVar->SetFloatValue( flHDRColorScale ); } } length = VectorLength( delta ); float flMaxWidth = MAX(startWidth, endWidth) * 0.5f; div = 1.0 / (segments-1); if ( length*div < flMaxWidth * 1.414 ) { // Here, we have too many segments; we could get overlap... so lets have less segments segments = (int)(length / (flMaxWidth * 1.414)) + 1; if ( segments < 2 ) { segments = 2; } } if ( segments > noise_divisions ) // UNDONE: Allow more segments? { segments = noise_divisions; } div = 1.0 / (segments-1); length *= 0.01; // UNDONE: Expose texture length scale factor to control "fuzziness" if ( flags & FBEAM_NOTILE ) { // Don't tile vStep = div; } else { // Texture length texels per space pixel vStep = length*div; } // UNDONE: Expose this paramter as well(3.5)? Texture scroll rate along beam vLast = fmod(freq*speed,1); // Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) if ( flags & FBEAM_SINENOISE ) { if ( segments < 16 ) { segments = 16; div = 1.0 / (segments-1); } scale *= 100; length = segments * (1.0/10); } else { scale *= length; } // Iterator to resample noise waveform (it needs to be generated in powers of 2) noiseStep = (int)((float)(noise_divisions-1) * div * 65536.0f); noiseIndex = 0; if ( flags & FBEAM_SINENOISE ) { noiseIndex = 0; } brightness = 1.0; if ( flags & FBEAM_SHADEIN ) { brightness = 0; } // What fraction of beam should be faded Assert( fadeLength >= 0.0f ); float fadeFraction = fadeLength/ delta.Length(); // BUGBUG: This code generates NANs when fadeFraction is zero! REVIST! fadeFraction = clamp(fadeFraction,1.e-6f,1.f); // Choose two vectors that are perpendicular to the beam Vector perp1; ComputeBeamPerpendicular( delta, &perp1 ); // Specify all the segments. CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); CBeamSegDraw segDraw; segDraw.Start( pRenderContext, segments, NULL ); for ( i = 0; i < segments; i++ ) { Assert( noiseIndex < (noise_divisions<<16) ); BeamSeg_t curSeg; curSeg.m_flAlpha = 1; fraction = i * div; // Fade in our out beam to fadeLength if ( (flags & FBEAM_SHADEIN) && (flags & FBEAM_SHADEOUT) ) { if (fraction < 0.5) { brightness = 2*(fraction/fadeFraction); } else { brightness = 2*(1.0 - (fraction/fadeFraction)); } } else if ( flags & FBEAM_SHADEIN ) { brightness = fraction/fadeFraction; } else if ( flags & FBEAM_SHADEOUT ) { brightness = 1.0 - (fraction/fadeFraction); } // clamps if (brightness < 0 ) { brightness = 0; } else if (brightness > 1) { brightness = 1; } VectorScale( *((Vector*)color), brightness, curSeg.m_vColor ); // UNDONE: Make this a spline instead of just a line? VectorMA( source, fraction, delta, curSeg.m_vPos ); // Distort using noise if ( scale != 0 ) { factor = prgNoise[noiseIndex>>16] * scale; if ( flags & FBEAM_SINENOISE ) { float s, c; SinCos( fraction*M_PI*length + freq, &s, &c ); VectorMA( curSeg.m_vPos, factor * s, CurrentViewUp(), curSeg.m_vPos ); // Rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal VectorMA( curSeg.m_vPos, factor * c, CurrentViewRight(), curSeg.m_vPos ); } else { VectorMA( curSeg.m_vPos, factor, perp1, curSeg.m_vPos ); } } // Specify the next segment. if( endWidth == startWidth ) { curSeg.m_flWidth = startWidth * 2; } else { curSeg.m_flWidth = ((fraction*(endWidth-startWidth))+startWidth) * 2; } curSeg.m_flTexCoord = vLast; segDraw.NextSeg( &curSeg ); vLast += vStep; // Advance texture scroll (v axis only) noiseIndex += noiseStep; }