void ParticleSystem::DrawParticle(particle *part, vec3_t &right, vec3_t &up) { float fSize = part->m_fSize; vec3_t point1,point2,point3,point4; vec3_t origin = part->origin; // nothing to draw? if (fSize == 0) return; //frustrum visible check if(!ParticleIsVisible(part)) return; float fCosSize = CosLookup(part->m_fAngle)*fSize; float fSinSize = SinLookup(part->m_fAngle)*fSize; // calculate the four corners of the sprite VectorMA (origin, fSinSize, up, point1); VectorMA (point1, -fCosSize, right, point1); VectorMA (origin, fCosSize, up, point2); VectorMA (point2, fSinSize, right, point2); VectorMA (origin, -fSinSize, up, point3); VectorMA (point3, fCosSize, right, point3); VectorMA (origin, -fCosSize, up, point4); VectorMA (point4, -fSinSize, right, point4); struct model_s * pModel; int iContents = 0; for (particle *pDraw = part; pDraw; pDraw = pDraw->m_pOverlay) { if (pDraw->pType->m_hSprite == 0) continue; if (pDraw->pType->m_iDrawCond) { if (iContents == 0) iContents = gEngfuncs.PM_PointContents(origin, NULL); if (iContents != pDraw->pType->m_iDrawCond) continue; } pModel = (struct model_s *)gEngfuncs.GetSpritePointer( pDraw->pType->m_hSprite ); // if we've reached the end of the sprite's frames, loop back while (pDraw->frame > pModel->numframes) pDraw->frame -= pModel->numframes; while (pDraw->frame < 0) pDraw->frame += pModel->numframes; if ( !gEngfuncs.pTriAPI->SpriteTexture( pModel, int(pDraw->frame) ))continue; gEngfuncs.pTriAPI->RenderMode(pDraw->pType->m_iRenderMode); gEngfuncs.pTriAPI->Color4f( pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue, pDraw->m_fAlpha ); gEngfuncs.pTriAPI->Begin( TRI_QUADS ); gEngfuncs.pTriAPI->TexCoord2f (0, 0); gEngfuncs.pTriAPI->Vertex3fv(point1); gEngfuncs.pTriAPI->TexCoord2f (1, 0); gEngfuncs.pTriAPI->Vertex3fv (point2); gEngfuncs.pTriAPI->TexCoord2f (1, 1); gEngfuncs.pTriAPI->Vertex3fv (point3); gEngfuncs.pTriAPI->TexCoord2f (0, 1); gEngfuncs.pTriAPI->Vertex3fv (point4); gEngfuncs.pTriAPI->End(); } }
bool ParticleSystem::UpdateParticle(particle *part, float frametime) { if (frametime == 0 ) return true; part->age += frametime; cl_entity_t *source = UTIL_GetClientEntityWithServerIndex( m_iEntIndex ); // is this particle bound to an entity? if (part->m_iEntIndex) { if (enable) { if(m_iEntAttachment) { part->velocity = (source->attachment[m_iEntAttachment - 1] - part->origin)/frametime; part->origin = source->attachment[m_iEntAttachment - 1]; } else { part->velocity = (source->curstate.origin - part->origin)/frametime; part->origin = source->curstate.origin; } } else { // entity is switched off, die return false; } } else { // not tied to an entity, check whether it's time to die if (part->age_death >= 0 && part->age > part->age_death) return false; // apply acceleration and velocity vec3_t vecOldPos = part->origin; if (part->m_fDrag) VectorMA(part->velocity, -part->m_fDrag*frametime, part->velocity - part->m_vecWind, part->velocity); VectorMA(part->velocity, frametime, part->accel, part->velocity); VectorMA(part->origin, frametime, part->velocity, part->origin); if (part->pType->m_bBouncing) { vec3_t vecTarget; VectorMA(part->origin, frametime, part->velocity, vecTarget); pmtrace_t *tr = gEngfuncs.PM_TraceLine( part->origin, vecTarget, PM_TRACELINE_PHYSENTSONLY, 2, -1 ); if (tr->fraction < 1) { part->origin = tr->endpos; float bounceforce = DotProduct(tr->plane.normal, part->velocity); float newspeed = (1 - part->pType->m_BounceFriction.GetInstance()); part->velocity = part->velocity * newspeed; VectorMA(part->velocity, -bounceforce*(newspeed+part->pType->m_Bounce.GetInstance()), tr->plane.normal, part->velocity); } } } // spray children if (part->age_spray && part->age > part->age_spray) { part->age_spray = part->age + 1/part->pType->m_SprayRate.GetInstance(); //particle *pChild = ActivateParticle(); if (part->pType->m_pSprayType) { particle *pChild = part->pType->m_pSprayType->CreateParticle(this); if (pChild) { pChild->origin = part->origin; float fSprayForce = part->pType->m_SprayForce.GetInstance(); pChild->velocity = part->velocity; if (fSprayForce) { float fSprayPitch = part->pType->m_SprayPitch.GetInstance() - source->curstate.angles.x; float fSprayYaw = part->pType->m_SprayYaw.GetInstance() - source->curstate.angles.y; float fSprayRoll = source->curstate.angles.z; float fForceCosPitch = fSprayForce*CosLookup(fSprayPitch); pChild->velocity.x += CosLookup(fSprayYaw) * fForceCosPitch; pChild->velocity.y += SinLookup(fSprayYaw) * fForceCosPitch + SinLookup(fSprayYaw) * fSprayForce * SinLookup(fSprayRoll); pChild->velocity.z -= SinLookup(fSprayPitch) * fSprayForce * CosLookup(fSprayRoll); } } } } part->m_fSize += part->m_fSizeStep * frametime; part->m_fAlpha += part->m_fAlphaStep * frametime; part->m_fRed += part->m_fRedStep * frametime; part->m_fGreen += part->m_fGreenStep * frametime; part->m_fBlue += part->m_fBlueStep * frametime; part->frame += part->m_fFrameStep * frametime; if (part->m_fAngleStep) { part->m_fAngle += part->m_fAngleStep * frametime; while (part->m_fAngle < 0) part->m_fAngle += 360; while (part->m_fAngle > 360) part->m_fAngle -= 360; } return true; }
bool ParticleSystem::UpdateParticle( particle *part, float frametime ) { if( frametime == 0 ) return true; part->age += frametime; edict_t *source = GetEntityByIndex( m_iEntIndex ); if( !source ) return false; // total paranoia :) // is this particle bound to an entity? if( part->m_iEntIndex ) { if ( enable ) { if( m_iEntAttachment ) { Vector pos = Vector( 0, 0, 0 ); GET_ATTACHMENT( source, m_iEntAttachment, pos, NULL ); if( pos == Vector( 0, 0, 0 )) pos = source->v.origin; // missed attachment part->velocity = (pos - part->origin ) / frametime; part->origin = pos; } else { part->velocity = ( source->v.origin - part->origin ) / frametime; part->origin = source->v.origin; } } else { // entity is switched off, die return false; } } else { // not tied to an entity, check whether it's time to die if( part->age_death >= 0 && part->age > part->age_death ) return false; // apply acceleration and velocity Vector vecOldPos = part->origin; if ( part->m_fDrag ) part->velocity = part->velocity + (-part->m_fDrag * frametime) * ( part->velocity - part->m_vecWind ); part->velocity = part->velocity + frametime * part->accel; part->origin = part->origin + frametime * part->velocity; if( part->pType->m_bBouncing ) { Vector vecTarget = part->origin + frametime * part->velocity; TraceResult tr; TRACE_LINE( part->origin, vecTarget, true, source, &tr ); if( tr.flFraction < 1.0f ) { part->origin = tr.vecEndPos; float bounceforce = DotProduct( tr.vecPlaneNormal, part->velocity ); float newspeed = (1.0f - part->pType->m_BounceFriction.GetInstance()); part->velocity = part->velocity * newspeed; part->velocity = part->velocity + (-bounceforce * ( newspeed + part->pType->m_Bounce.GetInstance())) * tr.vecPlaneNormal; } } } // spray children if ( part->age_spray && part->age > part->age_spray ) { part->age_spray = part->age + 1/part->pType->m_SprayRate.GetInstance(); // particle *pChild = ActivateParticle(); if (part->pType->m_pSprayType) { particle *pChild = part->pType->m_pSprayType->CreateParticle(this); if (pChild) { pChild->origin = part->origin; float fSprayForce = part->pType->m_SprayForce.GetInstance(); pChild->velocity = part->velocity; if (fSprayForce) { float fSprayPitch = part->pType->m_SprayPitch.GetInstance() - source->v.angles.x; float fSprayYaw = part->pType->m_SprayYaw.GetInstance() - source->v.angles.y; float fSprayRoll = source->v.angles.z; float fForceCosPitch = fSprayForce*CosLookup(fSprayPitch); pChild->velocity.x += CosLookup(fSprayYaw) * fForceCosPitch; pChild->velocity.y += SinLookup(fSprayYaw) * fForceCosPitch + SinLookup(fSprayYaw) * fSprayForce * SinLookup(fSprayRoll); pChild->velocity.z -= SinLookup(fSprayPitch) * fSprayForce * CosLookup(fSprayRoll); } } } } part->m_fSize += part->m_fSizeStep * frametime; part->m_fAlpha += part->m_fAlphaStep * frametime; part->m_fRed += part->m_fRedStep * frametime; part->m_fGreen += part->m_fGreenStep * frametime; part->m_fBlue += part->m_fBlueStep * frametime; part->frame += part->m_fFrameStep * frametime; if ( part->m_fAngleStep ) { part->m_fAngle += part->m_fAngleStep * frametime; while ( part->m_fAngle < 0 ) part->m_fAngle += 360; while ( part->m_fAngle > 360 ) part->m_fAngle -= 360; } return true; }
void ParticleSystem::DrawParticle( particle *part, Vector &right, Vector &up ) { float fSize = part->m_fSize; Vector point1, point2, point3, point4; Vector origin = part->origin; // nothing to draw? if ( fSize == 0 ) return; // frustrum visible check if( !ParticleIsVisible( part )) return; float fCosSize = CosLookup( part->m_fAngle ) * fSize; float fSinSize = SinLookup( part->m_fAngle ) * fSize; // calculate the four corners of the sprite point1 = origin + fSinSize * up; point1 = point1 + (-fCosSize) * right; point2 = origin + fCosSize * up; point2 = point2 + fSinSize * right; point3 = origin + (-fSinSize) * up; point3 = point3 + fCosSize * right; point4 = origin + (-fCosSize) * up; point4 = point4 + (-fSinSize) * right; int iContents = 0; g_engfuncs.pTriAPI->Enable( TRI_SHADER ); for ( particle *pDraw = part; pDraw; pDraw = pDraw->m_pOverlay ) { if( pDraw->pType->m_SpriteIndex == 0 ) continue; if ( pDraw->pType->m_iDrawCond ) { if ( iContents == 0 ) iContents = POINT_CONTENTS( origin ); if ( iContents != pDraw->pType->m_iDrawCond ) continue; } int numFrames = GetModelFrames( pDraw->pType->m_SpriteIndex ); // ALERT( at_console, "UpdParticle %d: age %f, life %f, R:%f G:%f, B, %f \n", pDraw->pType->m_hSprite, part->age, part->age_death, pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue); // if we've reached the end of the sprite's frames, loop back while ( pDraw->frame > numFrames ) pDraw->frame -= numFrames; while ( pDraw->frame < 0 ) pDraw->frame += numFrames; HSPRITE m_hSprite; m_hSprite = g_engfuncs.pTriAPI->GetSpriteTexture( pDraw->pType->m_SpriteIndex, int( pDraw->frame )); g_engfuncs.pTriAPI->RenderMode( pDraw->pType->m_iRenderMode ); g_engfuncs.pTriAPI->Color4f( pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue, pDraw->m_fAlpha ); g_engfuncs.pTriAPI->Bind( m_hSprite, int( pDraw->frame )); g_engfuncs.pTriAPI->Begin( TRI_QUADS ); g_engfuncs.pTriAPI->TexCoord2f ( 0, 0 ); g_engfuncs.pTriAPI->Vertex3fv( point1 ); g_engfuncs.pTriAPI->TexCoord2f ( 1, 0 ); g_engfuncs.pTriAPI->Vertex3fv ( point2 ); g_engfuncs.pTriAPI->TexCoord2f ( 1, 1 ); g_engfuncs.pTriAPI->Vertex3fv ( point3 ); g_engfuncs.pTriAPI->TexCoord2f ( 0, 1 ); g_engfuncs.pTriAPI->Vertex3fv ( point4 ); g_engfuncs.pTriAPI->End(); } g_engfuncs.pTriAPI->Disable( TRI_SHADER ); }
void CParticleSystem :: DrawParticle( CParticle *part, Vector &right, Vector &up ) { float fSize = part->m_fSize; // nothing to draw? if( fSize <= 0 ) return; // frustrum visible check if( !ParticleIsVisible( part )) return; Vector point1, point2, point3, point4; Vector origin = part->origin; float fCosSize = CosLookup( part->m_fAngle ) * fSize; float fSinSize = SinLookup( part->m_fAngle ) * fSize; // calculate the four corners of the sprite point1 = origin + up * fSinSize + right * -fCosSize; point2 = origin + up * fCosSize + right * fSinSize; point3 = origin + up * -fSinSize + right * fCosSize; point4 = origin + up * -fCosSize + right * -fSinSize; int iContents = CONTENTS_NONE; model_t *pModel; for( CParticle *pDraw = part; pDraw; pDraw = pDraw->m_pOverlay ) { if( !pDraw->pType->m_hSprite ) continue; if( pDraw->pType->m_iDrawCond ) { if( pDraw->pType->m_iDrawCond == CONTENT_SPOTLIGHT ) { if( !R_CountPlights( )) continue; // fast reject for( int i = 0; i < MAX_PLIGHTS; i++ ) { plight_t *pl = &cl_plights[i]; if( pl->die < GET_CLIENT_TIME() || !pl->radius ) continue; if( !R_CullSphereExt( pl->frustum, part->origin, part->m_fSize + 1, pl->clipflags )) break; // cone intersected with particle } if( i == MAX_PLIGHTS ) continue; // no intersection } else { if( iContents == CONTENTS_NONE ) iContents = POINT_CONTENTS( origin ); if( iContents != pDraw->pType->m_iDrawCond ) continue; } } pModel = (model_t *)gEngfuncs.GetSpritePointer( pDraw->pType->m_hSprite ); // if we've reached the end of the sprite's frames, loop back while (pDraw->frame > pModel->numframes) pDraw->frame -= pModel->numframes; while (pDraw->frame < 0) pDraw->frame += pModel->numframes; if( !TriSpriteTexture( pModel, (int)pDraw->frame )) continue; gEngfuncs.pTriAPI->RenderMode( pDraw->pType->m_iRenderMode ); if( m_iLightingModel >= 1 ) { color24 lightColor; Vector lightingColor; if( m_iLightingModel == 1 ) R_LightForPoint( part->origin, &lightColor, false, true, fSize + 1 ); else R_LightForPoint( part->origin, &lightColor, false, true, 0.0f ); // FIXME: this code is totally wrong. // We need a fake lightmap here like in sprite implementation lightingColor.x = pDraw->m_fRed * lightColor.r * (1.0f / 255.0f); lightingColor.y = pDraw->m_fGreen * lightColor.g * (1.0f / 255.0f); lightingColor.z = pDraw->m_fBlue * lightColor.b * (1.0f / 255.0f); pglColor4f( lightingColor.x, lightingColor.y, lightingColor.z, pDraw->m_fAlpha ); } else pglColor4f( pDraw->m_fRed, pDraw->m_fGreen, pDraw->m_fBlue, pDraw->m_fAlpha ); pglBegin( GL_QUADS ); pglTexCoord2f( 0.0f, 0.0f ); pglVertex3fv( point1 ); pglTexCoord2f( 1.0f, 0.0f ); pglVertex3fv( point2 ); pglTexCoord2f( 1.0f, 1.0f ); pglVertex3fv( point3 ); pglTexCoord2f( 0.0f, 1.0f ); pglVertex3fv( point4 ); pglEnd(); if( m_iLightingModel >=2 && R_CountPlights( )) { for( int i = 0; i < MAX_PLIGHTS; i++ ) { plight_t *pl = &cl_plights[i]; if( pl->die < GET_CLIENT_TIME() || !pl->radius ) continue; if( R_CullSphereExt( pl->frustum, part->origin, part->m_fSize + 1, pl->clipflags )) continue; R_BeginDrawProjection( pl ); pglBegin( GL_QUADS ); pglVertex3fv( point1 ); pglVertex3fv( point2 ); pglVertex3fv( point3 ); pglVertex3fv( point4 ); pglEnd(); R_EndDrawProjection(); } } } }