123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- static const char *smokeParticle_SnapshotName = "_SmokeParticle_Snapshot_";
- idSmokeParticles::idSmokeParticles() {
- initialized = false;
- memset( &renderEntity, 0, sizeof( renderEntity ) );
- renderEntityHandle = -1;
- memset( smokes, 0, sizeof( smokes ) );
- freeSmokes = NULL;
- numActiveSmokes = 0;
- currentParticleTime = -1;
- }
- void idSmokeParticles::Init() {
- if ( initialized ) {
- Shutdown();
- }
-
- for ( int i = 0; i < MAX_SMOKE_PARTICLES-1; i++ ) {
- smokes[i].next = &smokes[i+1];
- }
- smokes[MAX_SMOKE_PARTICLES-1].next = NULL;
- freeSmokes = &smokes[0];
- numActiveSmokes = 0;
- activeStages.Clear();
- memset( &renderEntity, 0, sizeof( renderEntity ) );
- renderEntity.bounds.Clear();
- renderEntity.axis = mat3_identity;
- renderEntity.shaderParms[ SHADERPARM_RED ] = 1;
- renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1;
- renderEntity.shaderParms[ SHADERPARM_BLUE ] = 1;
- renderEntity.shaderParms[3] = 1;
- renderEntity.hModel = renderModelManager->AllocModel();
- renderEntity.hModel->InitEmpty( smokeParticle_SnapshotName );
-
- renderEntity.noShadow = 1;
-
- renderEntity.bounds.AddPoint( idVec3(-100000, -100000, -100000) );
- renderEntity.bounds.AddPoint( idVec3( 100000, 100000, 100000) );
- renderEntity.callback = idSmokeParticles::ModelCallback;
-
- renderEntityHandle = gameRenderWorld->AddEntityDef( &renderEntity );
- currentParticleTime = -1;
- initialized = true;
- }
- void idSmokeParticles::Shutdown() {
-
- if ( renderEntityHandle != -1 ) {
- gameRenderWorld->FreeEntityDef( renderEntityHandle );
- renderEntityHandle = -1;
- }
- if ( renderEntity.hModel != NULL ) {
- renderModelManager->FreeModel( renderEntity.hModel );
- renderEntity.hModel = NULL;
- }
- initialized = false;
- }
- void idSmokeParticles::FreeSmokes() {
- for ( int activeStageNum = 0; activeStageNum < activeStages.Num(); activeStageNum++ ) {
- singleSmoke_t *smoke, *next, *last;
- activeSmokeStage_t *active = &activeStages[activeStageNum];
- const idParticleStage *stage = active->stage;
- for ( last = NULL, smoke = active->smokes; smoke; smoke = next ) {
- next = smoke->next;
- float frac;
- if ( smoke->timeGroup ) {
- frac = (float)( gameLocal.fast.time - smoke->privateStartTime ) / ( stage->particleLife * 1000 );
- }
- else {
- frac = (float)( gameLocal.slow.time - smoke->privateStartTime ) / ( stage->particleLife * 1000 );
- }
- if ( frac >= 1.0f ) {
-
- if ( last != NULL ) {
- last->next = smoke->next;
- } else {
- active->smokes = smoke->next;
- }
-
- smoke->next = freeSmokes;
- freeSmokes = smoke;
- numActiveSmokes--;
- continue;
- }
- last = smoke;
- }
- if ( !active->smokes ) {
-
- activeStages.RemoveIndex( activeStageNum );
- activeStageNum--;
- }
- }
- }
- bool idSmokeParticles::EmitSmoke( const idDeclParticle *smoke, const int systemStartTime, const float diversity, const idVec3 &origin, const idMat3 &axis, int timeGroup ) {
- bool continues = false;
- SetTimeState ts( timeGroup );
- if ( !smoke ) {
- return false;
- }
- if ( !gameLocal.isNewFrame ) {
- return false;
- }
-
- if ( gameLocal.GetLocalClientNum() < 0 ) {
- return false;
- }
- assert( gameLocal.time == 0 || systemStartTime <= gameLocal.time );
- if ( systemStartTime > gameLocal.time ) {
- return false;
- }
- idRandom steppingRandom( 0xffff * diversity );
-
- for ( int stageNum = 0; stageNum < smoke->stages.Num(); stageNum++ ) {
- const idParticleStage *stage = smoke->stages[stageNum];
- if ( !stage->cycleMsec ) {
- continue;
- }
- if ( !stage->material ) {
- continue;
- }
- if ( stage->particleLife <= 0 ) {
- continue;
- }
-
-
- int finalParticleTime = stage->cycleMsec * stage->spawnBunching;
- int deltaMsec = gameLocal.time - systemStartTime;
- int nowCount = 0, prevCount = 0;
- if ( finalParticleTime == 0 ) {
-
- if ( gameLocal.time == systemStartTime ) {
- prevCount = -1;
- nowCount = stage->totalParticles-1;
- } else {
- prevCount = stage->totalParticles;
- }
- } else {
- nowCount = floor( ( (float)deltaMsec / finalParticleTime ) * stage->totalParticles );
- if ( nowCount >= stage->totalParticles ) {
- nowCount = stage->totalParticles-1;
- }
- prevCount = floor( ((float)( deltaMsec - ( gameLocal.time - gameLocal.previousTime ) ) / finalParticleTime) * stage->totalParticles );
- if ( prevCount < -1 ) {
- prevCount = -1;
- }
- }
- if ( prevCount >= stage->totalParticles ) {
-
- continue;
- }
- if ( nowCount < stage->totalParticles-1 ) {
-
- continues = true;
- }
-
- activeSmokeStage_t *active = NULL;
- int i;
- for ( i = 0 ; i < activeStages.Num() ; i++ ) {
- active = &activeStages[i];
- if ( active->stage == stage ) {
- break;
- }
- }
- if ( i == activeStages.Num() ) {
-
- activeSmokeStage_t newActive;
- newActive.smokes = NULL;
- newActive.stage = stage;
- i = activeStages.Append( newActive );
- active = &activeStages[i];
- }
-
- for ( prevCount++ ; prevCount <= nowCount && active != NULL ; prevCount++ ) {
- if ( !freeSmokes ) {
- gameLocal.Printf( "idSmokeParticles::EmitSmoke: no free smokes with %d active stages\n", activeStages.Num() );
- return true;
- }
- singleSmoke_t *newSmoke = freeSmokes;
- freeSmokes = freeSmokes->next;
- numActiveSmokes++;
- newSmoke->timeGroup = timeGroup;
- newSmoke->index = prevCount;
- newSmoke->axis = axis;
- newSmoke->origin = origin;
- newSmoke->random = steppingRandom;
- newSmoke->privateStartTime = systemStartTime + prevCount * finalParticleTime / stage->totalParticles;
- newSmoke->next = active->smokes;
- active->smokes = newSmoke;
- steppingRandom.RandomInt();
- }
- }
- return continues;
- }
- bool idSmokeParticles::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) {
-
-
- if ( !renderView ) {
-
- renderEntity->hModel->InitEmpty( smokeParticle_SnapshotName );
- return false;
- }
-
- if ( renderView->time[renderEntity->timeGroup] == currentParticleTime && !renderView->forceUpdate ) {
- return false;
- }
-
- renderEntity->hModel->InitEmpty( smokeParticle_SnapshotName );
- currentParticleTime = renderView->time[renderEntity->timeGroup];
- particleGen_t g;
- g.renderEnt = renderEntity;
- g.renderView = renderView;
- for ( int activeStageNum = 0; activeStageNum < activeStages.Num(); activeStageNum++ ) {
- singleSmoke_t *smoke, *next, *last;
- activeSmokeStage_t *active = &activeStages[activeStageNum];
- const idParticleStage *stage = active->stage;
- if ( !stage->material ) {
- continue;
- }
-
- int count = 0;
- for ( smoke = active->smokes; smoke; smoke = smoke->next ) {
- count++;
- }
- int quads = count * stage->NumQuadsPerParticle();
- srfTriangles_t *tri = renderEntity->hModel->AllocSurfaceTriangles( quads * 4, quads * 6 );
- tri->numIndexes = quads * 6;
- tri->numVerts = quads * 4;
-
- tri->bounds[0][0] =
- tri->bounds[0][1] =
- tri->bounds[0][2] = -99999;
- tri->bounds[1][0] =
- tri->bounds[1][1] =
- tri->bounds[1][2] = 99999;
- tri->numVerts = 0;
- for ( last = NULL, smoke = active->smokes; smoke; smoke = next ) {
- next = smoke->next;
- if ( smoke->timeGroup ) {
- g.frac = (float)( gameLocal.fast.time - smoke->privateStartTime ) / (stage->particleLife * 1000);
- }
- else {
- g.frac = (float)( gameLocal.time - smoke->privateStartTime ) / (stage->particleLife * 1000);
- }
- if ( g.frac >= 1.0f ) {
-
- if ( last != NULL ) {
- last->next = smoke->next;
- } else {
- active->smokes = smoke->next;
- }
-
- smoke->next = freeSmokes;
- freeSmokes = smoke;
- numActiveSmokes--;
- continue;
- }
- g.index = smoke->index;
- g.random = smoke->random;
- g.origin = smoke->origin;
- g.axis = smoke->axis;
- g.originalRandom = g.random;
- g.age = g.frac * stage->particleLife;
- tri->numVerts += stage->CreateParticle( &g, tri->verts + tri->numVerts );
- last = smoke;
- }
- if ( tri->numVerts > quads * 4 ) {
- gameLocal.Error( "idSmokeParticles::UpdateRenderEntity: miscounted verts" );
- }
- if ( tri->numVerts == 0 ) {
-
- renderEntity->hModel->FreeSurfaceTriangles( tri );
- if ( !active->smokes ) {
-
- activeStages.RemoveIndex( activeStageNum );
- activeStageNum--;
- }
- } else {
-
- int indexes = 0;
- for ( int i = 0 ; i < tri->numVerts ; i += 4 ) {
- tri->indexes[indexes+0] = i;
- tri->indexes[indexes+1] = i+2;
- tri->indexes[indexes+2] = i+3;
- tri->indexes[indexes+3] = i;
- tri->indexes[indexes+4] = i+3;
- tri->indexes[indexes+5] = i+1;
- indexes += 6;
- }
- tri->numIndexes = indexes;
- modelSurface_t surf;
- surf.geometry = tri;
- surf.shader = stage->material;
- surf.id = 0;
- renderEntity->hModel->AddSurface( surf );
- }
- }
- return true;
- }
- bool idSmokeParticles::ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) {
-
- if ( gameLocal.smokeParticles ) {
- return gameLocal.smokeParticles->UpdateRenderEntity( renderEntity, renderView );
- }
- return true;
- }
|