Beispiel #1
0
void
cGrCloudLayer::build( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition )
{
  layer_span = span;
  layer_asl = elevation;
  layer_thickness = thickness;
  layer_transition = transition;

  scale = 4000.0;
  last_lon = last_lat = -999.0f;
  last_x = last_y = 0.0f;

  sgVec2 base;
  sgSetVec2( base, (float)grRandom(), (float)grRandom() );

  // build the cloud layer
  sgVec4 color;
  sgVec3 vertex;
  sgVec2 tc;

  const float layer_scale = layer_span / scale;
  const float mpi = SG_PI/4;
  const float alt_diff = layer_asl * 1.5f;

  for (int i = 0; i < 4; i++) 
  {
    if ( layer[i] != NULL ) 
    {
      layer_transform->removeKid(layer[i]); // automatic delete
    }

    vl[i] = new ssgVertexArray( 10 );
    cl[i] = new ssgColourArray( 10 );
    tl[i] = new ssgTexCoordArray( 10 );

    sgSetVec3( vertex, layer_span*(i-2)/2, -layer_span,
      (float)(alt_diff * (sin(i*mpi) - 2)) );

    sgSetVec2( tc, base[0] + layer_scale * i/4, base[1] );

    sgSetVec4( color, 1.0f, 1.0f, 1.0f, (i == 0) ? 0.0f : 0.15f );

    cl[i]->add( color );
    vl[i]->add( vertex );
    tl[i]->add( tc );

    for (int j = 0; j < 4; j++) 
    {
      sgSetVec3( vertex, layer_span*(i-1)/2, layer_span*(j-2)/2,
        (float)(alt_diff * (sin((i+1)*mpi) + sin(j*mpi) - 2)) );

      sgSetVec2( tc, base[0] + layer_scale * (i+1)/4,
        base[1] + layer_scale * j/4 );

      sgSetVec4( color, 1.0f, 1.0f, 1.0f,
        ( (j == 0) || (i == 3)) ?  
        ( (j == 0) && (i == 3)) ? 0.0f : 0.15f : 1.0f );

      cl[i]->add( color );
      vl[i]->add( vertex );
      tl[i]->add( tc );

      sgSetVec3( vertex, layer_span*(i-2)/2, layer_span*(j-1)/2,
        (float)(alt_diff * (sin(i*mpi) + sin((j+1)*mpi) - 2)) );

      sgSetVec2( tc, base[0] + layer_scale * i/4,
        base[1] + layer_scale * (j+1)/4 );

      sgSetVec4( color, 1.0f, 1.0f, 1.0f,
        ((j == 3) || (i == 0)) ?
        ((j == 3) && (i == 0)) ? 0.0f : 0.15f : 1.0f );
      cl[i]->add( color );
      vl[i]->add( vertex );
      tl[i]->add( tc );
    }

    sgSetVec3( vertex, layer_span*(i-1)/2, layer_span, 
      (float)(alt_diff * (sin((i+1)*mpi) - 2)) );

    sgSetVec2( tc, base[0] + layer_scale * (i+1)/4,
    base[1] + layer_scale );

    sgSetVec4( color, 1.0f, 1.0f, 1.0f, (i == 3) ? 0.0f : 0.15f );

    cl[i]->add( color );
    vl[i]->add( vertex );
    tl[i]->add( tc );

    layer[i] = new ssgVtxTable(GL_TRIANGLE_STRIP, vl[i], NULL, tl[i], cl[i]);
    layer_transform->addKid( layer[i] );

    layer[i]->setState( cloud_state );
  }

  // force a repaint of the sky colors with arbitrary defaults
  repaint( color );
}
Beispiel #2
0
void cGrSky::modifyVisibility( float alt, float time_factor )
{
  float effvis = visibility;

  for ( int i = 0; i < clouds.getNum (); ++i )
  {
    cGrCloudLayer *cloud = clouds.get(i);

    if ( cloud->isEnabled() )
    {
      float asl = cloud->getElevation();
      float thickness = cloud->getThickness();
      float transition = cloud->getTransition();

      float ratio = 1.0;

      if ( alt < asl - transition )
      {
        // below cloud layer
        ratio = 1.0;
      }
      else if ( alt < asl )
      {
        // in lower transition
        ratio = (asl - alt) / transition;
      }
      else if ( alt < asl + thickness )
      {
        // in cloud layer
        ratio = 0.0;
      }
      else if ( alt < asl + thickness + transition )
      {
        // in upper transition
        ratio = (alt - (asl + thickness)) / transition;
      }
      else
      {
        // above cloud layer
        ratio = 1.0;
      }

      // accumulate effects from multiple cloud layers
      effvis *= ratio;

      if ( ratio < 1.0 )
      {
        if ( ! in_puff )
        {
          // calc chance of entering cloud puff
          double rnd = grRandom();
          double chance = rnd * rnd * rnd;
          if ( chance > 0.95 )
          {
            in_puff = true;
            puff_length = grRandom() * 2.0; // up to 2 seconds
            puff_progression = 0.0;
          }
        }

	if ( in_puff )
	{
	  // modify actual_visibility based on puff envelope
	  if ( puff_progression <= ramp_up )
	  {
	    double x = 0.5 * SGD_PI * puff_progression / ramp_up;
	    double factor = 1.0 - sin( x );
	    effvis = (float)(effvis * factor);
	  }
	  else if ( puff_progression >= ramp_up + puff_length )
	  {
	    double x = 0.5 * SGD_PI *
	      (puff_progression - (ramp_up + puff_length)) /
	      ramp_down;
	    double factor = sin( x );
	    effvis = (float)(effvis * factor);
	  }
	  else
  	  {
            effvis = 0.0;
          }

          puff_progression += time_factor;

	  if ( puff_progression > puff_length + ramp_up + ramp_down)
	  {
	    in_puff = false;
	  }
	}

        // never let visibility drop below 25 meters
        if ( effvis <= 25.0 )
        {
          effvis = 25.0;
        }
       }
     }
  } // for

  effective_visibility = effvis;
}