bool PitMorph::DoSequence( TimeClock* timeClock ) { const float SPEED = 4.0f * ( TERRAIN_HEIGHT / 10.0f ); // m term in y = mx+b const float SLOPE = 1.0f; bool last = false; Lilith3D* lilith = Lilith3D::Instance(); TerrainMesh* tmesh = lilith->GetTerrainMesh(); float height = tmesh->Height( terrainX, terrainY ) - timeClock->CalcVelocity( SPEED ); height = Clamp( height, TERRAIN_MIN, TERRAIN_MAX ); // essentially the x-intecept: // y = mx + b, b=height // x = -height / m float radius = ( TERRAIN_MAX - height ) / SLOPE; int irad = int( radius ) + 1; Rectangle2I bounds; bounds.Set( terrainX - irad, terrainY - irad, terrainX + irad, terrainY + irad ); Rectangle2I constrain; constrain.Set( 0, 0, lilith3d::VERTEXSIZE-1, lilith3d::VERTEXSIZE-1 ); bounds.DoIntersection( constrain ); // Do the center first. if ( height <= altitude ) last = true; if ( tmesh->Height( terrainX, terrainY ) > altitude ) { tmesh->StartHeightChange(); tmesh->SetHeight( terrainX, terrainY, height ); for( int j=bounds.min.y; j<=bounds.max.y; ++j ) { for( int i=bounds.min.x; i<=bounds.max.x; ++i ) { if ( i != terrainX || j != terrainY ) { float len = Length( float( terrainX-i ), float( terrainY-j ), 0.0f ); float setHeight = len*SLOPE + height; if ( setHeight < tmesh->Height( i, j ) ) tmesh->SetHeight( i, j, setHeight ); } } } tmesh->EndHeightChange(); } for( Publisher< PitMorphListener >::const_iterator it = publish.begin(); it != publish.end(); ++it ) { if ( last ) (*it)->PitDone( this, terrainX, terrainY, height ); else (*it)->PitSink( this, terrainX, terrainY, height ); } return last; }
bool VolcanoMorph::DoSequence( TimeClock* timeClock ) { const float SPEED = 4.0f * ( TERRAIN_HEIGHT / 10.0f ); // m term in y = mx+b const float SLOPE = -1.3f; const float SMOOTH_RADIUS = 3.0f; bool last = false; Lilith3D* lilith = Lilith3D::Instance(); TerrainMesh* tmesh = lilith->GetTerrainMesh(); float height = tmesh->Height( terrainX, terrainY ) + timeClock->CalcVelocity( SPEED ); height = Clamp( height, TERRAIN_MIN, TERRAIN_MAX ); // essentially the x-intecept: // y = mx + b, b=height // x = -height / m float radius = -( height - TERRAIN_MIN ) / SLOPE; int irad = int( radius ) + 1; Rectangle2I bounds; bounds.Set( terrainX - irad, terrainY - irad, terrainX + irad, terrainY + irad ); Rectangle2I constrain; constrain.Set( 0, 0, lilith3d::VERTEXSIZE-1, lilith3d::VERTEXSIZE-1 ); bounds.DoIntersection( constrain ); // Do the center first. if ( height >= altitude ) last = true; if ( tmesh->Height( terrainX, terrainY ) < altitude ) { tmesh->StartHeightChange(); tmesh->SetHeight( terrainX, terrainY, height ); for( int j=bounds.min.y; j<=bounds.max.y; ++j ) { for( int i=bounds.min.x; i<=bounds.max.x; ++i ) { if ( i != terrainX || j != terrainY ) { float len = Length( float( terrainX-i ), float( terrainY-j ) ); float setHeight = len*SLOPE + height; if ( len < SMOOTH_RADIUS ) setHeight += fuzzHeight[ (j*lilith3d::VERTEXSIZE+i) % FUZZ_SIZE ]; if ( setHeight > tmesh->Height( i, j ) ) tmesh->SetHeight( i, j, setHeight ); } } } tmesh->EndHeightChange(); } // Inform listeners of changes. for( Publisher< VolcanoMorphListener >::const_iterator it = publish.begin(); it != publish.end(); ++it ) { if ( !last ) (*it)->VolcanoGrow( this, terrainX, terrainY, height ); else (*it)->VolcanoDone( this, terrainX, terrainY, height ); } // And now the particles and lights! const float FUZZ = 4.0f; const float FUZZMORE = 8.0f; float alt = tmesh->Height( terrainX, terrainY ); GravParticles* grav = lilith->GetGravParticles(); TimeClock* tc = Lilith3D::GetTimeClock(); while ( tc->Msec() > lastParticleTime ) { lastParticleTime += 50; Vector3F loc = { (float)terrainX, (float)terrainY, alt }; Vector3F vel = { -FUZZ / 2 + rand.FRand( FUZZ ), // velocity -FUZZ / 2 + rand.FRand( FUZZ ), SPEED * 1.3f }; Color3F col = { 0.8f + rand.FRand(0.2f), // coloring 0.6f + rand.FRand(0.2f), 0.0f }; grav->Create( loc, vel, col, GravParticles::GRAVITY, 1.0f, GravParticles::FLAME0 ); for( int i=0; i<3; ++i ) { Vector3F vel2 = { -FUZZMORE / 2 + rand.FRand( FUZZMORE ), -FUZZMORE / 2 + rand.FRand( FUZZMORE ), SPEED * 0.8f }; Color3F col2 = { 1.0f, 0.0f, 0.0f }; grav->Create( loc, vel2, col2, GravParticles::GRAVITY, GravParticles::MEDIUM ); } } // glowLight->SetPos( (float)terrainX, (float)terrainY, alt ); if ( decal ) { decal->SetAlpha( 1.0f ); const float FADEOUT = 0.8f * altitude; if ( alt > FADEOUT ) { decal->SetAlpha( Interpolate( FADEOUT, 1.0f, altitude, 0.0f, alt )); } } return last; }