Exemple #1
0
void TerraformPrepare () 
{


  int         x, y;
  Region      r;
  GLcoord     from_center;
  GLcoord     offset;

  //Set some defaults
  offset.x = RandomVal () % 1024;
  offset.y = RandomVal () % 1024;
  for (x = 0; x < WORLD_GRID; x++) {
    for (y = 0; y < WORLD_GRID; y++) {
      memset (&r, 0, sizeof (Region));
      sprintf (r.title, "NOTHING");
      r.geo_bias = r.geo_detail = 0;
      r.mountain_height = 0;
      r.grid_pos.x = x;
      r.grid_pos.y = y;
      r.tree_threshold = 0.15f;
      from_center.x = abs (x - WORLD_GRID_CENTER);
      from_center.y = abs (y - WORLD_GRID_CENTER);
      //Geo scale is a number from -1 to 1. -1 is lowest ocean. 0 is sea level. 
      //+1 is highest elevation on the island. This is used to guide other derived numbers.
      r.geo_scale = glVectorLength (glVector ((float)from_center.x, (float)from_center.y));
      r.geo_scale /= (WORLD_GRID_CENTER - OCEAN_BUFFER);
      //Create a steep drop around the edge of the world
      if (r.geo_scale > 1.0f)
        r.geo_scale = 1.0f + (r.geo_scale - 1.0f) * 4.0f;
      r.geo_scale = 1.0f - r.geo_scale;
      r.geo_scale += (Entropy ((x + offset.x), (y + offset.y)) - 0.5f);
      r.geo_scale += (Entropy ((x + offset.x) * FREQUENCY, (y + offset.y) * FREQUENCY) - 0.2f);
      r.geo_scale = clamp (r.geo_scale, -1.0f, 1.0f);
      if (r.geo_scale > 0.0f)
        r.geo_water = 1.0f + r.geo_scale * 16.0f;
      r.color_atmosphere = glRgba (0.0f, 0.0f, 0.0f);
      r.geo_bias = 0.0f;
      r.geo_detail = 0.0f;
      r.color_map = glRgba (0.0f);
      r.climate = CLIMATE_INVALID;
      WorldRegionSet (x, y, r);
    }
  }

}
Exemple #2
0
void CLight::Blink ()
{

    _blink = true;
    //we don't want blinkers to be in sync, so have them blink at
    //slightly different rates. (Milliseconds)
    _blink_interval = 1500 + RandomVal (500);

}
Exemple #3
0
//Drop a point in the middle of the terrain and attempt to
//place a river. 
void TerraformRivers (int count)
{

  int         rivers;
  int         cycles;
  int         x, y;
  int         range;

  rivers = 0;
  cycles = 0;
  range = WORLD_GRID_CENTER / 3;
  while (rivers < count && cycles < 100) {
    x = WORLD_GRID_CENTER + (RandomVal () % range) - range / 2;
    y = WORLD_GRID_CENTER + (RandomVal () % range) - range / 2;
    if (try_river (x, y, rivers)) 
      rivers++;
    cycles++;
  }

}
Exemple #4
0
//look around the map and find an unused area of the desired size
static bool find_plot (int radius, GLcoord* result)
{

  int       cycles;
  GLcoord   test;
  
  cycles = 0;
  while (cycles < 20) {
    cycles++;
    test.x = RandomVal () % WORLD_GRID;
    test.y = RandomVal () % WORLD_GRID;
    if (is_free (test.x, test.y, radius)) {
      *result = test;
      return true;
    }
  }
  //couldn't find a spot. Map is full, or just bad dice rolls. 
  return false; 

}
Exemple #5
0
void CBuilding::ConstructCube (int left, int right, int front, int back, int bottom, int top)
{

  GLvertex    p[10];
  float       x1, x2, z1, z2, y1, y2;
  int         i;
  cube        c;
  float       u, v1, v2;
  float       mapping;
  int         base_index;
  int         height;

  height = top - bottom;
  x1 = (float)left;
  x2 = (float)right;
  y1 = (float)bottom;
  y2 = (float)top;
  z1 = (float)front;
  z2 = (float)back;
  base_index = _mesh->VertexCount ();

  mapping = (float)SEGMENTS_PER_TEXTURE;
  u = (float)(RandomVal () % SEGMENTS_PER_TEXTURE) / (float)SEGMENTS_PER_TEXTURE;
  v1 = (float)bottom / (float)mapping;
  v2 = (float)top / (float)mapping;

  p[0].position = glVector (x1, y1, z1);  p[0].uv = glVector (u, v1);
  p[1].position = glVector (x1, y2, z1);  p[1].uv = glVector (u, v2);
  u += (float)_width / mapping;
  p[2].position = glVector (x2, y1, z1);  p[2].uv = glVector (u, v1);
  p[3].position = glVector (x2, y2, z1);  p[3].uv = glVector (u, v2);
  u += (float)_depth / mapping;
  p[4].position = glVector (x2, y1, z2);  p[4].uv = glVector (u, v1);
  p[5].position = glVector (x2, y2, z2);  p[5].uv = glVector (u, v2);
  u += (float)_width / mapping;
  p[6].position = glVector (x1, y1, z2);  p[6].uv = glVector (u, v1);
  p[7].position = glVector (x1, y2, z2);  p[7].uv = glVector (u, v2);
  u += (float)_width / mapping;
  p[8].position = glVector (x1, y1, z1);  p[8].uv = glVector (u, v1);
  p[9].position = glVector (x1, y2, z1);  p[9].uv = glVector (u, v2);
  for (i = 0; i < 10; i++) {
    p[i].uv.x = (p[i].position.x + p[i].position.z) / (float)SEGMENTS_PER_TEXTURE;
    _mesh->VertexAdd (p[i]);
    c.index_list.push_back(base_index + i);
  }
  _mesh->CubeAdd (c);

}
Exemple #6
0
static void window (int x, int y, int size, int id, GLrgba color)
{

  int     margin;
  int     half;
  int     i;

  margin = size / 3;
  half = size / 2;
  switch (id) {
  case TEXTURE_BUILDING1: //filled, 1-pixel frame
    drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);
    break;
  case TEXTURE_BUILDING2: //vertical
    drawrect (x + margin, y + 1, x + size - margin, y + size - 1, color);
    break;
  case TEXTURE_BUILDING3: //side-by-side pair
    drawrect (x + 1, y + 1, x + half - 1, y + size - margin, color);
    drawrect (x + half + 1, y + 1, x + size - 1, y + size - margin,  color);
    break;
  case TEXTURE_BUILDING4: //windows with blinds
    drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);
    i = RandomVal (size - 2);
    drawrect (x + 1, y + 1, x + size - 1, y + i + 1, color * 0.3f);

    break;
  case TEXTURE_BUILDING5: //vert stripes
    drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);
    drawrect (x + margin, y + 1, x + margin, y + size - 1, color * 0.7f);
    drawrect (x + size - margin - 1, y + 1, x + size - margin - 1, y + size - 1, color * 0.3f);
    break;
  case TEXTURE_BUILDING6: //wide horz line
    drawrect (x + 1, y + 1, x + size - 1, y + size - margin, color);
    break;
  case TEXTURE_BUILDING7: //4-pane
    drawrect (x + 2, y + 1, x + size - 1, y + size - 1, color);
    drawrect (x + 2, y + half, x + size - 1, y + half, color * 0.2f);
    drawrect (x + half, y + 1, x + half, y + size - 1, color * 0.2f);
    break;
  case TEXTURE_BUILDING8: // Single narrow window
    drawrect (x + half - 1, y + 1, x + half + 1, y + size - margin, color);
    break;
  case TEXTURE_BUILDING9: //horizontal
    drawrect (x + 1, y + margin, x + size - 1, y + size - margin - 1, color);
    break;
  }

}
Exemple #7
0
CBuilding::CBuilding (int type, int x, int y, int height, int width, int depth, int seed, GLrgba color)
{

  _x = x;
  _y = y;
  _width = width;
  _depth = depth;
  _height = height;
  _center = glVector ((float)(_x + width / 2), 0.0f, (float)(_y + depth / 2));
  _seed = seed;
  _texture_type = RandomVal ();
  _color = color;
  _color.alpha = 0.1f;
  _have_lights = false;
  _have_logo = false;
  _have_trim = false;
  _roof_tiers = 0;
  //Pick a color for logos & roof lights
  _trim_color = WorldLightColor (seed);
  _mesh = new CMesh; //The main textured mesh for the building
  _mesh_flat = new CMesh; //Flat-color mesh for untextured detail items.
  switch (type) {
  case BUILDING_SIMPLE:
    CreateSimple ();
    break;  
  case BUILDING_MODERN: 
    CreateModern (); 
    break;
  case BUILDING_TOWER: 
    CreateTower (); 
    break;
  case BUILDING_BLOCKY:
    CreateBlocky (); 
    break;
  }

}
Exemple #8
0
void CTexture::DrawWindows()
{
	int x, y;
	int run = 0;
	int run_length = 2;
	int lit_density = 2;
	GLrgba color;
	bool lit = false;

	//color = glRgbaUnique (_my_id);
	for (y = 0; y < SEGMENTS_PER_TEXTURE; y++)
	{
		//Every few floors we change the behavior
		if ((y % 8) == 0)
		{
			run = 0;
			run_length = RandomVal(9) + 2;
			lit_density = 2 + RandomVal(2) + RandomVal(2);
			lit = false;
		}
		for (x = 0; x < SEGMENTS_PER_TEXTURE; x++)
		{
			//if this run is over reroll lit and start a new one
			if (run < 1)
			{
				run = RandomVal(run_length);
				lit = RandomVal(lit_density) == 0;
				//if (lit)
				//color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);
			}
			if (lit)
				color = glRgba(0.5f + (float)(RandomVal() % 128) / 256.0f) + glRgba(RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);
			else
				color = glRgba((float)(RandomVal() % 40) / 256.0f);
			window(x * _segment_size, y * _segment_size, _segment_size, _my_id, color);
			run--;
		}
	}
}
Exemple #9
0
//Gives a 1 in 'odds' chance of adding flowers to the given region
void add_flowers (Region* r, unsigned odds)
{

  GLrgba    c;
  int       shape;

  r->has_flowers = RandomVal () % odds == 0;
  shape = RandomVal ();
  c = flower_palette[RandomVal () % FLOWER_PALETTE];
  for (int i = 0; i < FLOWERS; i++) {
    r->color_flowers[i] = c;
    r->flower_shape[i] = shape;
    if ((RandomVal () % 15) == 0) {
      shape = RandomVal ();
      c = flower_palette[RandomVal () % FLOWER_PALETTE];
    }
  }


}
Exemple #10
0
void CBuilding::CreateTower ()
{

  int         left, right, front, back, bottom;
  int         section_height, section_width, section_depth;
  int         remaining_height;
  int         ledge_height;
  int         tier_fraction;
  int         grouping;
  int         foundation;
  int         narrowing_interval;
  int         tiers;
  float       ledge;
  float       uv_start;
  bool        blank_corners;
  bool        roof_spike;
  bool        tower;

  //How much ledges protrude from the building
  ledge = (float)RandomVal (3) * 0.25f;
  //How tall the ledges are, in stories
  ledge_height = RandomVal (4) + 1;
  //How the windows are grouped
  grouping = RandomVal (3) + 2;
  //if the corners of the building have no windows
  blank_corners = RandomVal (4) > 0;
  //if the roof is pointed or has infrastructure on it
  roof_spike = RandomVal (3) == 0;
  //What fraction of the remaining height should be given to each tier
  tier_fraction = 2 + RandomVal (4);
  //How often (in tiers) does the building get narrorwer?
  narrowing_interval = 1 + RandomVal (10);
  //The height of the windowsless slab at the bottom
  foundation = 2 + RandomVal (3);
  //The odds that we'll have a big fancy spikey top
  tower = RandomVal (5) != 0 && _height > 40;
  //set our initial parameters
  left = _x; 
  right = _x + _width;
  front = _y;
  back = _y + _depth;
  bottom = 0;
  tiers = 0;
  //build the foundations.
  ConstructCube ((float)left - ledge, (float)right + ledge, (float)front - ledge, (float)back + ledge, (float)bottom, (float)foundation);
  bottom += foundation;
  //now add tiers until we reach the top
  while (1) {
    remaining_height = _height - bottom;
    section_depth = back - front;
    section_width = right - left;
    section_height = MAX (remaining_height / tier_fraction, 2);
    if (remaining_height < 10)
      section_height = remaining_height;
    //Build the four walls
    uv_start = (float)RandomVal (SEGMENTS_PER_TEXTURE) / SEGMENTS_PER_TEXTURE;
    uv_start = ConstructWall (left, bottom, back, SOUTH, section_depth, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
    uv_start = ConstructWall (left, bottom, front, EAST, section_width, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
    uv_start = ConstructWall (right, bottom, front, NORTH, section_depth, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
    uv_start = ConstructWall (right, bottom, back, WEST, section_width, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
    bottom += section_height;
    //Build the slab / ledges to cap this section.
    if (bottom + ledge_height > _height)
      break;
    ConstructCube ((float)left - ledge, (float)right + ledge, (float)front - ledge, (float)back + ledge, (float)bottom, (float)(bottom + ledge_height));
    bottom += ledge_height;
    if (bottom > _height)
      break;
    tiers++;
    if ((tiers % narrowing_interval) == 0) {
      if (section_width > 7) {
        left+=1;
        right-=1;
      }
      if (section_depth > 7) {
        front+=1;
        back-=1;
      }
    }
  }
  ConstructRoof ((float)left, (float)right, (float)front, (float)back, (float)bottom);
  _mesh->Compile ();
  _mesh_flat->Compile ();

}
Exemple #11
0
void CBuilding::CreateModern ()
{

  GLvertex    p;
  GLvector    center;
  GLvector    pos;
  GLvector2   radius;
  GLvector2   start, end;
  int         angle;
  int         windows;
  int         cap_height;
  int         half_depth, half_width;
  float       dist;
  float       length;
  quad_strip  qs;
  fan         f;
  int         points;
  int         skip_interval;
  int         skip_counter;
  int         skip_delta;
  int         i;
  bool        logo_done;
  bool        do_trim;
  CDeco*      d;

  logo_done = false;
  //How tall the windowless section on top will be.
  cap_height = 1 + RandomVal (5);
  //How many 10-degree segments to build before the next skip.
  skip_interval = 1 + RandomVal (8);
  //When a skip happens, how many degrees should be skipped
  skip_delta = (1 + RandomVal (2)) * 30; //30 60 or 90
  //See if this is eligible for fancy lighting trim on top
  if (_height > 48 && RandomVal (3) == 0)
    do_trim = true;
  else
    do_trim = false;
  //Get the center and radius of the circle
  half_depth = _depth / 2;
  half_width = _width / 2;
  center = glVector ((float)(_x + half_width), 0.0f, (float)(_y + half_depth));
  radius = glVector ((float)half_width, (float)half_depth);
  dist = 0;
  windows = 0;
  p.uv.x = 0.0f;
  points = 0;
  skip_counter = 0;
  for (angle = 0; angle <= 360; angle += 10) {
    if (skip_counter >= skip_interval && (angle + skip_delta < 360)) {
      angle += skip_delta;
      skip_counter = 0;
    }
    pos.x = center.x - sinf ((float)angle * DEGREES_TO_RADIANS) * radius.x;
    pos.z = center.z + cosf ((float)angle * DEGREES_TO_RADIANS) * radius.y;
    if (angle > 0 && skip_counter == 0) {
      length = MathDistance (p.position.x, p.position.z, pos.x, pos.z);
      windows += (int)length;
      if (length > 10 && !logo_done) {
        logo_done = true;
        start = glVector (pos.x, pos.z);
        end = glVector (p.position.x, p.position.z);
        d = new CDeco;
        d->CreateLogo (start, end, (float)_height, WorldLogoIndex (), RANDOM_COLOR);
      }
    } else if (skip_counter != 1)
      windows++;
    p.position = pos;
    p.uv.x = (float)windows / (float)SEGMENTS_PER_TEXTURE;
    p.uv.y = 0.0f;
    p.position.y = 0.0f;
    _mesh->VertexAdd (p);
    p.position.y = (float)_height;
    p.uv.y = (float)_height / (float)SEGMENTS_PER_TEXTURE;
    _mesh->VertexAdd (p);
    _mesh_flat->VertexAdd (p);
    p.position.y += (float)cap_height;
    _mesh_flat->VertexAdd (p);
    vector_buffer[points / 2] = p.position;
    vector_buffer[points / 2].y = (float)_height + cap_height / 4;
    points += 2;
    skip_counter++;
  }
  //if this is a big building and it didn't get a logo, consider giving it a light strip
  if (!logo_done && do_trim) {
    d = new CDeco;
    d->CreateLightTrim (vector_buffer, (points / 2) - 2, (float)cap_height / 2, _seed, RANDOM_COLOR);
  }
  qs.index_list.reserve(points);   
  //Add the outer walls
  for (i = 0; i < points; i++)
    qs.index_list.push_back(i);
  _mesh->QuadStripAdd (qs);
  _mesh_flat->QuadStripAdd (qs);
  //add the fan to cap the top of the buildings
  f.index_list.push_back(points);
  for (i = 0; i < points / 2; i++)
    f.index_list.push_back(points - (1 + i * 2));
  p.position.x = _center.x;
  p.position.z = _center.z;
  _mesh_flat->VertexAdd (p);
  _mesh_flat->FanAdd (f);
  radius /= 2.0f;
  //ConstructRoof ((int)(_center.x - radius), (int)(_center.x + radius), (int)(_center.z - radius), (int)(_center.z + radius), _height + cap_height);
  _mesh->Compile ();
  _mesh_flat->Compile ();

}
Exemple #12
0
void CBuilding::CreateSimple ()
{

  GLvertex    p;
  float       x1, x2, z1, z2, y1, y2;
  quad_strip  qs;
  float       u, v1, v2;
  float       cap_height;
  float       ledge;

  for(int i=0; i<10; i++)
    qs.index_list.push_back(i);

  //How tall the flat-color roof is
  cap_height = (float)(1 + RandomVal (4));
  //how much the ledge sticks out
  ledge = (float)RandomVal (10) / 30.0f;

  x1 = (float)_x;
  x2 = (float)(_x + _width);
  y1 = (float)0.0f;
  y2 = (float)_height;
  z2 = (float)_y;
  z1 = (float)(_y + _depth);

  u = (float)(RandomVal (SEGMENTS_PER_TEXTURE)) / SEGMENTS_PER_TEXTURE;
  v1 = (float)(RandomVal (SEGMENTS_PER_TEXTURE)) / SEGMENTS_PER_TEXTURE;
  v2 = v1 + (float)_height * ONE_SEGMENT;

  p.position = glVector (x1, y1, z1);  p.uv = glVector (u, v1);
  _mesh->VertexAdd (p);
  p.position = glVector (x1, y2, z1);  p.uv = glVector (u, v2);
  _mesh->VertexAdd (p);
  u += (float)_depth / SEGMENTS_PER_TEXTURE;

  p.position = glVector (x1, y1, z2);  p.uv = glVector (u, v1);
  _mesh->VertexAdd (p);
  p.position = glVector (x1, y2, z2);  p.uv = glVector (u, v2);
  _mesh->VertexAdd (p);
  u += (float)_width / SEGMENTS_PER_TEXTURE;
  
  p.position = glVector (x2, y1, z2);  p.uv = glVector (u, v1);
  _mesh->VertexAdd (p);
  p.position = glVector (x2, y2, z2);  p.uv = glVector (u, v2);
  _mesh->VertexAdd (p);
  u += (float)_depth / SEGMENTS_PER_TEXTURE;

  p.position = glVector (x2, y1, z1);  p.uv = glVector (u, v1);
  _mesh->VertexAdd (p);
  p.position = glVector (x2, y2, z1);  p.uv = glVector (u, v2);
  _mesh->VertexAdd (p);
  u += (float)_depth / SEGMENTS_PER_TEXTURE;

  p.position = glVector (x1, y1, z1);  p.uv = glVector (u, v1);
  _mesh->VertexAdd (p);
  p.position = glVector (x1, y2, z1);  p.uv = glVector (u, v2);
  _mesh->VertexAdd (p);

  _mesh->QuadStripAdd (qs);
  ConstructCube (x1 - ledge, x2 + ledge, z2 - ledge, z1 + ledge, (float)_height, (float)_height + cap_height);
  _mesh->Compile ();

}
Exemple #13
0
//Create zones of different climates.
void TerraformZones ()
{

  int             x, y;
  vector<Climate> climates;
  Region          r;
  int             radius;
  Climate         c;
  GLcoord         walk;
  UINT            spinner;

  walk.Clear ();
  spinner = 0;
  do {
    x = walk.x;
    y = walk.y;// + WorldNoisei (walk.x + walk.y * WORLD_GRID) % 4;
    radius = 2 + WorldNoisei (10 + walk.x + walk.y * WORLD_GRID) % 9;
    if (is_free (x, y, radius)) {
      r = WorldRegionGet (x, y);
      climates.clear ();
      //swamps only appear in wet areas that aren't cold.
      if (r.moisture > 0.8f && r.temperature > 0.5f)
        climates.push_back (CLIMATE_SWAMP);
      //mountains only appear in the middle
      if (abs (x - WORLD_GRID_CENTER) < 10 && radius > 1)
        climates.push_back (CLIMATE_MOUNTAIN);
      //Deserts are HOT and DRY. Duh.
      if (r.temperature > TEMP_HOT && r.moisture < 0.05f && radius > 1)
        climates.push_back (CLIMATE_DESERT);
      //fields should be not too hot or cold.
      if (r.temperature > TEMP_TEMPERATE && r.temperature < TEMP_HOT && r.moisture > 0.5f && radius == 1)
        climates.push_back (CLIMATE_FIELD);
      if (r.temperature > TEMP_TEMPERATE && r.temperature < TEMP_HOT && r.moisture > 0.25f && radius > 1)
        climates.push_back (CLIMATE_PLAINS);
      //Rocky wastelands favor cold areas
      if (r.temperature < TEMP_TEMPERATE)
        climates.push_back (CLIMATE_ROCKY);
      if (radius > 1 && !(WorldNoisei (spinner++) % 10))
        climates.push_back (CLIMATE_CANYON);
      if (r.temperature > TEMP_TEMPERATE && r.temperature < TEMP_HOT && r.moisture > 0.5f)
        climates.push_back (CLIMATE_FOREST);
      if (climates.empty ()) {
        walk.Walk (WORLD_GRID);
        continue;
      }              
      c = climates[RandomVal () % climates.size ()];
      switch (c) {
      case CLIMATE_ROCKY:
        do_rocky (x, y, radius);
        break;
      case CLIMATE_MOUNTAIN:
        do_mountain (x, y, radius);
        break;
      case CLIMATE_CANYON:
        do_canyon (x, y, radius);
        break;
      case CLIMATE_SWAMP:
        do_swamp (x, y, radius);
        break;
      case CLIMATE_FIELD:
        do_field (x, y, radius);
        break;
      case CLIMATE_DESERT:
        do_desert (x, y, radius);
        break;
      case CLIMATE_PLAINS:
        do_plains (x, y, radius);
        break;
      case CLIMATE_FOREST:
        do_forest (x, y, radius);
        break;
      }
    }
  } while (!walk.Walk (WORLD_GRID));

}
Exemple #14
0
void CBuilding::CreateBlocky ()
{

  int         min_height;
  int         left, right, front, back;
  int         max_left, max_right, max_front, max_back;
  int         height;
  int         mid_x, mid_z;
  int         half_depth, half_width;
  int         tiers;
  int         max_tiers;
  int         grouping;
  float       lid_height;
  float       uv_start;
  bool        skip;
  bool        blank_corners;

  //Choose if the corners of the building are to be windowless.
  blank_corners = COIN_FLIP;
  //Choose a random column on our texture;
  uv_start = (float)RandomVal (SEGMENTS_PER_TEXTURE) / SEGMENTS_PER_TEXTURE;
  //Choose how the windows are grouped
  grouping = 2 + RandomVal (4);
  //Choose how tall the lid should be on top of each section
  lid_height = (float)(RandomVal (3) + 1);
  //find the center of the building.
  mid_x = _x + _width / 2;
  mid_z = _y + _depth / 2;
  max_left = max_right = max_front = max_back = 1;
  height = _height;
  min_height = _height / 2;
  min_height = 3;
  half_depth = _depth / 2;
  half_width = _width / 2;
  tiers = 0;
  if (_height > 40)
    max_tiers = 15;
  else if (_height > 30)
    max_tiers = 10;
  else if (_height > 20)
    max_tiers = 5;
  else if (_height > 10)
    max_tiers = 2;
  else
    max_tiers = 1;
  //We begin at the top of the building, and work our way down.
  //Viewed from above, the sections of the building are randomly sized
  //rectangles that ALWAYS include the center of the building somewhere within 
  //their area.  
  while (1) {
    if (height < min_height)
      break;
    if (tiers >= max_tiers)
      break;
    //pick new locationsfor our four outer walls
    left = (RandomVal () % half_width) + 1;
    right = (RandomVal () % half_width) + 1;
    front = (RandomVal () % half_depth) + 1;
    back = (RandomVal () % half_depth) + 1;
    skip = false;
    //At least ONE of the walls must reach out beyond a previous maximum.
    //Otherwise, this tier would be completely hidden within a previous one.
    if (left <= max_left && right <= max_right && front <= max_front && back <= max_back) 
      skip = true;
    //If any of the four walls is in the same position as the previous max,then
    //skip this tier, or else the two walls will end up z-fightng.
    if (left == max_left || right == max_right || front == max_front || back == max_back) 
      skip = true;
    if (!skip) {
      //if this is the top, then put some lights up here
      max_left = MAX (left, max_left);
      max_right = MAX (right, max_right);
      max_front = MAX (front, max_front);
      max_back = MAX (back, max_back);
      //Now build the four walls of this part
      uv_start = ConstructWall (mid_x - left, 0, mid_z + back, SOUTH, front + back, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
      uv_start = ConstructWall (mid_x - left, 0, mid_z - front, EAST, right + left, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
      uv_start = ConstructWall (mid_x + right, 0, mid_z - front, NORTH, front + back, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
      uv_start = ConstructWall (mid_x + right, 0, mid_z + back, WEST, right + left, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;
      if (!tiers)
        ConstructRoof ((float)(mid_x - left), (float)(mid_x + right), (float)(mid_z - front), (float)(mid_z + back), (float)height);
      else //add a flat-color lid onto this section
        ConstructCube ((float)(mid_x - left), (float)(mid_x + right), (float)(mid_z - front), (float)(mid_z + back), (float)height, (float)height + lid_height);
      height -= (RandomVal () % 10) + 1;
      tiers++;
    }
    height--;
  }
  ConstructCube (mid_x - half_width, mid_x + half_width, mid_z - half_depth, mid_z + half_depth, 0, 2);
  _mesh->Compile ();
  _mesh_flat->Compile ();

}
Exemple #15
0
void CBuilding::ConstructRoof (float left, float right, float front, float back, float bottom)
{

  int       air_conditioners;
  int       i;
  int       width, depth, height;
  int       face;
  int       addon = ADDON_NONE;
  int       max_tiers;
  float     ac_x;
  float     ac_y;
  float     ac_base;
  float     ac_size;
  float     ac_height;
  float     tower_height;
  float     logo_offset;
  CDeco*    d;
  GLvector2 start, end;

  _roof_tiers++;
  max_tiers = _height / 10;
  width = (int)(right - left);
  depth = (int)(back - front);
  height = 5 - _roof_tiers;
  logo_offset = 0.2f;
  //See if this building is special and worthy of fancy roof decorations.
  if (bottom > 35.0f)
    addon = RandomVal (ADDON_COUNT);
  //Build the roof slab
  ConstructCube (left, right, front, back, bottom, bottom + (float)height);
  //Consider putting a logo on the roof, if it's tall enough
  if (addon == ADDON_LOGO && !_have_logo) {
    d = new CDeco;
    if (width > depth)
      face = COIN_FLIP ? NORTH : SOUTH;
    else
      face = COIN_FLIP ? EAST : WEST;
    switch (face) {
    case NORTH:
      start = glVector ((float)left, (float)back + logo_offset);
      end = glVector ((float)right, (float)back + logo_offset);
      break;
    case SOUTH:
      start = glVector ((float)right, (float)front - logo_offset);
      end = glVector ((float)left, (float)front - logo_offset);
      break;
    case EAST:
      start = glVector ((float)right + logo_offset, (float)back);
      end = glVector ((float)right + logo_offset, (float)front);
      break;
    case WEST:
    default:
      start = glVector ((float)left - logo_offset, (float)front);
      end = glVector ((float)left - logo_offset, (float)back);
      break;
    }
    d->CreateLogo (start, end, bottom, WorldLogoIndex (), _trim_color);
    _have_logo = true;
  } else if (addon == ADDON_TRIM) {
    d = new CDeco;
    vector_buffer[0] = glVector (left, bottom, back);
    vector_buffer[1] = glVector (left, bottom, front);
    vector_buffer[2] = glVector (right, bottom, front);
    vector_buffer[3] = glVector (right, bottom, back);
    d->CreateLightTrim (vector_buffer, 4, (float)RandomVal (2) + 1.0f, _seed, _trim_color);
  } else if (addon == ADDON_LIGHTS && !_have_lights) {
    new CLight (glVector (left, (float)(bottom + 2), front), _trim_color, 2);
    new CLight (glVector (right, (float)(bottom + 2), front), _trim_color, 2);
    new CLight (glVector (right, (float)(bottom + 2), back), _trim_color, 2);
    new CLight (glVector (left, (float)(bottom + 2), back), _trim_color, 2);
    _have_lights = true;
  }
  bottom += (float)height;
  //If the roof is big enough, consider making another layer 
  if (width > 7 && depth > 7 && _roof_tiers < max_tiers) {
    ConstructRoof (left + 1, right - 1, front + 1, back - 1, bottom);
    return;
  }
  //1 air conditioner block for every 15 floors sounds reasonble
  air_conditioners = _height / 15;
  for (i = 0; i < air_conditioners; i++) {
    ac_size = (float)(10 + RandomVal (30)) / 10;
    ac_height = (float)RandomVal (20) / 10 + 1.0f;
    ac_x = left + (float)RandomVal (width);
    ac_y = front + (float)RandomVal (depth);
    //make sure the unit doesn't hang off the right edge of the building
    if (ac_x + ac_size > (float)right)
      ac_x = (float)right - ac_size;
    //make sure the unit doesn't hang off the back edge of the building
    if (ac_y + ac_size > (float)back)
      ac_y = (float)back - ac_size;
    ac_base = (float)bottom;
    //make sure it doesn't hang off the edge
    ConstructCube (ac_x, ac_x + ac_size, ac_y, ac_y + ac_size, ac_base, ac_base + ac_height);
  }

  if (_height > 45) {
    d = new CDeco;
    tower_height = (float)(12 + RandomVal (8));
    d->CreateRadioTower (glVector ((float)(left + right) / 2.0f, (float)bottom, (float)(front + back) / 2.0f), 15.0f);
  }
  

}
Exemple #16
0
//This will fill in all previously un-assigned regions.
void TerraformFill ()
{

  int       x, y;
  Region    r;
  unsigned  rand;

  for (x = 0; x < WORLD_GRID; x++) {
    for (y = 0; y < WORLD_GRID; y++) {
      r = WorldRegionGet (x, y);
      //See if this is already ocean
      if (r.climate != CLIMATE_INVALID)
        continue;
      sprintf (r.title, "???");
      r.geo_water = r.geo_scale * 10.0f;
      r.geo_detail = 20.0f;
      //Have them trend more hilly in dry areas
      rand = RandomVal () % 8;
      if (r.moisture > 0.3f && r.temperature > 0.5f) {
        GLrgba    c;
        int       shape;
        
        r.has_flowers = RandomVal () % 4 == 0;
        shape = RandomVal ();
        c = flower_palette[RandomVal () % FLOWER_PALETTE];
        for (int i = 0; i < FLOWERS; i++) {
          r.color_flowers[i] = c;
          r.flower_shape[i] = shape;
          if ((RandomVal () % 15) == 0) {
            shape = RandomVal ();
            c = flower_palette[RandomVal () % FLOWER_PALETTE];
          }
        }
      }      
      if (rand == 0) {
        r.flags_shape |= REGION_FLAG_MESAS;
        sprintf (r.title, "Mesas");
      } else if (rand == 1) {
        sprintf (r.title, "Craters");
        r.flags_shape |= REGION_FLAG_CRATER;
      } else if (rand == 2) {
        sprintf (r.title, "TEST");
        r.flags_shape |= REGION_FLAG_TEST;
      } else if (rand == 3) {
        sprintf (r.title, "Sinkhole");
        r.flags_shape |= REGION_FLAG_SINKHOLE;
      } else if (rand == 4) {
        sprintf (r.title, "Crack");
        r.flags_shape |= REGION_FLAG_CRACK;
      } else if (rand == 5) {
        sprintf (r.title, "Tiered");
        r.flags_shape |= REGION_FLAG_TIERED;
      } else if (rand == 6) {
        sprintf (r.title, "Wasteland");
      } else {
        sprintf (r.title, "Grasslands");
        //r.geo_detail /= 3;
        //r.geo_large /= 3;
      }  
      WorldRegionSet (x, y, r);
    }
  }

}
Exemple #17
0
void CTexture::Rebuild()
{
	int i, j;
	int x, y;
	int name_num, prefix_num, suffix_num;
	int max_size;
	float radius;
	GLvector2 pos;
	bool use_framebuffer;
	unsigned char* bits;
	unsigned start;
	int lapsed;

	start = GetTickCount();
	//Since we make textures by drawing into the viewport, we can't make them bigger
	//than the current view.
	_size = _desired_size;
	max_size = RenderMaxTextureSize();
	while (_size > max_size)
		_size /= 2;
	glBindTexture(GL_TEXTURE_2D, _glid);
	//Set up the texture
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	if (_clamp)
	{
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}
	//Set up our viewport so that drawing into our texture will be as easy
	//as possible.  We make the viewport and projection simply match the given
	//texture size.
	glViewport(0, 0, _size, _size);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, _size, _size, 0, 0.1f, 2048);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glDisable(GL_CULL_FACE);
	glDisable(GL_FOG);
	glBindTexture(GL_TEXTURE_2D, 0);
	glTranslatef(0, 0, -10.0f);
	glClearColor(0, 0, 0, _masked ? 0.0f : 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	use_framebuffer = true;
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	switch (_my_id)
	{
		case TEXTURE_LATTICE:
			glLineWidth(2.0f);

			glColor3f(0, 0, 0);
			glBegin(GL_LINES);
			glVertex2i(0, 0);
			glVertex2i(_size, _size); //diagonal
			glVertex2i(0, 0);
			glVertex2i(0, _size); //vertical
			glVertex2i(0, 0);
			glVertex2i(_size, 0); //vertical
			glEnd();
			glBegin(GL_LINE_STRIP);
			glVertex2i(0, 0);
			for (i = 0; i < _size; i += 9)
			{
				if (i % 2)
					glVertex2i(0, i);
				else
					glVertex2i(i, i);
			}
			for (i = 0; i < _size; i += 9)
			{
				if (i % 2)
					glVertex2i(i, 0);
				else
					glVertex2i(i, i);
			}
			glEnd();
			break;
		case TEXTURE_SOFT_CIRCLE:
			//Make a simple circle of light, bright in the center and fading out
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			radius = ((float)_half) - 3;
			glBegin(GL_TRIANGLE_FAN);
			glColor4f(1, 1, 1, 1);
			glVertex2i(_half, _half);
			glColor4f(0, 0, 0, 0);
			for (i = 0; i <= 360; i++)
			{
				pos.x = sinf((float)i * DEGREES_TO_RADIANS) * radius;
				pos.y = cosf((float)i * DEGREES_TO_RADIANS) * radius;
				glVertex2i(_half + (int)pos.x, _half + (int)pos.y);
			}
			glEnd();
			break;
		case TEXTURE_LIGHT:
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			radius = ((float)_half) - 3;
			for (j = 0; j < 2; j++)
			{
				glBegin(GL_TRIANGLE_FAN);
				glColor4f(1, 1, 1, 1);
				glVertex2i(_half, _half);
				if (!j)
					radius = ((float)_half / 2);
				else
					radius = 8;
				glColor4f(1, 1, 1, 0);
				for (i = 0; i <= 360; i++)
				{
					pos.x = sinf((float)i * DEGREES_TO_RADIANS) * radius;
					pos.y = cosf((float)i * DEGREES_TO_RADIANS) * radius;
					glVertex2i(_half + (int)pos.x, _half + (int)pos.y);
				}
				glEnd();
			}
			break;
		case TEXTURE_HEADLIGHT:
			DrawHeadlight();
			break;
		case TEXTURE_LOGOS:
			i = 0;
			glDepthMask(false);
			glDisable(GL_BLEND);
			name_num = RandomVal(NAME_COUNT);
			prefix_num = RandomVal(PREFIX_COUNT);
			suffix_num = RandomVal(SUFFIX_COUNT);
			glColor3f(1, 1, 1);
			while (i < _size)
			{
				//randomly use a prefix OR suffix, but not both.  Too verbose.
				if (COIN_FLIP)
					RenderPrint(2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba(1.0f), "%s%s", prefix[prefix_num], name[name_num]);
				else
					RenderPrint(2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba(1.0f), "%s%s", name[name_num], suffix[suffix_num]);
				name_num = (name_num + 1) % NAME_COUNT;
				prefix_num = (prefix_num + 1) % PREFIX_COUNT;
				suffix_num = (suffix_num + 1) % SUFFIX_COUNT;
				i += LOGO_PIXELS;
			}
			break;
		case TEXTURE_TRIM:
			int margin;
			y = 0;
			margin = MAX(TRIM_PIXELS / 4, 1);
			for (x = 0; x < _size; x += TRIM_PIXELS)
				drawrect_simple(x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba(1.0f), glRgba(0.5f));
			y += TRIM_PIXELS;
			for (x = 0; x < _size; x += TRIM_PIXELS * 2)
				drawrect_simple(x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba(1.0f), glRgba(0.5f));
			y += TRIM_PIXELS;
			for (x = 0; x < _size; x += TRIM_PIXELS * 3)
				drawrect_simple(x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba(1.0f), glRgba(0.5f));
			y += TRIM_PIXELS;
			for (x = 0; x < _size; x += TRIM_PIXELS)
				drawrect_simple(x + margin, y + margin * 2, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba(1.0f), glRgba(0.5f));
			break;
		case TEXTURE_SKY:
			DrawSky();
			break;
		default: //building textures
			DrawWindows();
			break;
	}
	glPopMatrix();
	//Now blit the finished image into our texture
	if (use_framebuffer)
	{
		glBindTexture(GL_TEXTURE_2D, _glid);
		glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, _size, _size, 0);
	}
	if (_mipmap)
	{
		bits = (unsigned char*)malloc(_size * _size * 4);
		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits);
		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, _size, _size, GL_RGBA, GL_UNSIGNED_BYTE, bits);
		free(bits);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}
	else
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	//cleanup and restore the viewport
	RenderResize();
	_ready = true;
	lapsed = GetTickCount() - start;
	build_time += lapsed;
}
Exemple #18
0
void CTexture::DrawSky()
{
	GLrgba color;
	float grey;
	float scale, inv_scale;
	int i, x, y;
	int width, height;
	int offset;
	int width_adjust;
	int height_adjust;

	color = WorldBloomColor();
	grey = (color.red + color.green + color.blue) / 3.0f;
	//desaturate, slightly dim
	color = (color + glRgba(grey) * 2.0f) / 15.0f;
	glDisable(GL_BLEND);
	glBegin(GL_QUAD_STRIP);
	glColor3f(0, 0, 0);
	glVertex2i(0, _half);
	glVertex2i(_size, _half);
	glColor3fv(&color.red);
	glVertex2i(0, _size - 2);
	glVertex2i(_size, _size - 2);
	glEnd();
	//Draw a bunch of little faux-buildings on the horizon.
	for (i = 0; i < _size; i += 5)
		drawrect(i, _size - RandomVal(8) - RandomVal(8) - RandomVal(8), i + RandomVal(9), _size, glRgba(0.0f));
	//Draw the clouds
	for (i = _size - 30; i > 5; i -= 2)
	{
		x = RandomVal(_size);
		y = i;

		scale = 1.0f - ((float)y / (float)_size);
		width = RandomVal(_half / 2) + (int)((float)_half * scale) / 2;
		scale = 1.0f - (float)y / (float)_size;
		height = (int)((float)(width) * scale);
		height = MAX(height, 4);

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glDisable(GL_CULL_FACE);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, TextureId(TEXTURE_SOFT_CIRCLE));
		glDepthMask(false);
		glBegin(GL_QUADS);
		for (offset = -_size; offset <= _size; offset += _size)
		{
			for (scale = 1.0f; scale > 0.0f; scale -= 0.25f)
			{
				inv_scale = 1.0f - (scale);
				if (scale < 0.4f)
					color = WorldBloomColor() * 0.1f;
				else
					color = glRgba(0.0f);
				color.alpha = 0.2f;
				glColor4fv(&color.red);
				width_adjust = (int)((float)width / 2.0f + (int)(inv_scale * ((float)width / 2.0f)));
				height_adjust = height + (int)(scale * (float)height * 0.99f);
				glTexCoord2f(0, 0);
				glVertex2i(offset + x - width_adjust, y + height - height_adjust);
				glTexCoord2f(0, 1);
				glVertex2i(offset + x - width_adjust, y + height);
				glTexCoord2f(1, 1);
				glVertex2i(offset + x + width_adjust, y + height);
				glTexCoord2f(1, 0);
				glVertex2i(offset + x + width_adjust, y + height - height_adjust);
			}
		}
	}
	glEnd();
}
Exemple #19
0
void drawrect(int left, int top, int right, int bottom, GLrgba color)
{
	float average;
	float hue;
	int potential;
	int repeats;
	int height;
	int i, j;
	bool bright;
	GLrgba color_noise;

	glDisable(GL_CULL_FACE);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	glLineWidth(1.0f);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glColor3fv(&color.red);

	if (left == right)
	{ //in low resolution, a "rect" might be 1 pixel wide
		glBegin(GL_LINES);
		glVertex2i(left, top);
		glVertex2i(left, bottom);
		glEnd();
	}
	if (top == bottom)
	{ //in low resolution, a "rect" might be 1 pixel wide
		glBegin(GL_LINES);
		glVertex2i(left, top);
		glVertex2i(right, top);
		glEnd();
	}
	else
	{ // draw one of those fancy 2-dimensional rectangles
		glBegin(GL_QUADS);
		glVertex2i(left, top);
		glVertex2i(right, top);
		glVertex2i(right, bottom);
		glVertex2i(left, bottom);
		glEnd();


		average = (color.red + color.blue + color.green) / 3.0f;
		bright = average > 0.5f;
		potential = (int)(average * 255.0f);

		if (bright)
		{
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glBegin(GL_POINTS);
			for (i = left + 1; i < right - 1; i++)
			{
				for (j = top + 1; j < bottom - 1; j++)
				{
					glColor4i(255, 0, RandomVal(potential), 255);
					hue = 0.2f + (float)RandomVal(100) / 300.0f + (float)RandomVal(100) / 300.0f + (float)RandomVal(100) / 300.0f;
					color_noise = glRgbaFromHsl(hue, 0.3f, 0.5f);
					color_noise.alpha = (float)RandomVal(potential) / 144.0f;
					glColor4f(RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, (float)RandomVal(potential) / 144.0f);
					glColor4fv(&color_noise.red);
					glVertex2i(i, j);
				}
			}
			glEnd();
		}
		repeats = RandomVal(6) + 1;
		height = (bottom - top) + (RandomVal(3) - 1) + (RandomVal(3) - 1);
		for (i = left; i < right; i++)
		{
			if (RandomVal(3) == 0)
				repeats = RandomVal(4) + 1;
			if (RandomVal(6) == 0)
			{
				height = bottom - top;
				height = RandomVal(height);
				height = RandomVal(height);
				height = RandomVal(height);
				height = ((bottom - top) + height) / 2;
			}
			for (j = 0; j < 1; j++)
			{
				glBegin(GL_LINES);
				glColor4f(0, 0, 0, (float)RandomVal(256) / 256.0f);
				glVertex2i(i, bottom - height);
				glColor4f(0, 0, 0, (float)RandomVal(256) / 256.0f);
				glVertex2i(i, bottom);
				glEnd();
			}
		}
	}
}
Exemple #20
0
void CCar::Update (void)
{

  int       new_row, new_col;
  GLvector  old_pos;    
  GLvector  camera;

  //If the car isn't ready, place it on the map and get it moving
  camera = CameraPosition ();
  if (!m_ready) {
    //if the car isn't ready, we need to place it somewhere on the map
    m_row = DEAD_ZONE + RandomVal (WORLD_SIZE - DEAD_ZONE * 2);
    m_col = DEAD_ZONE + RandomVal (WORLD_SIZE - DEAD_ZONE * 2);
    //if there is already a car here, forget it.  
    if (carmap[m_row][m_col] > 0)
      return;
    //if this spot is not a road, forget it
    if (!(WorldCell (m_row, m_col) & CLAIM_ROAD)) 
      return;
    if (!Visible (glVector ((float)m_row, 0.0f, (float)m_col)))
      return;
    //good spot. place the car
    m_position = glVector ((float)m_row, 0.1f, (float)m_col);
    m_drive_position = m_position;
    m_ready = true;
    if (WorldCell (m_row, m_col) & MAP_ROAD_NORTH) 
      m_direction = NORTH;
    if (WorldCell (m_row, m_col) & MAP_ROAD_EAST) 
      m_direction = EAST;
    if (WorldCell (m_row, m_col) & MAP_ROAD_SOUTH) 
      m_direction = SOUTH;
    if (WorldCell (m_row, m_col) & MAP_ROAD_WEST) 
      m_direction = WEST;
    m_drive_angle = dangles[m_direction];
    m_max_speed = (float)(4 + RandomVal (6)) / 10.0f;
    m_speed = 0.0f;
    m_change = 3;
    m_stuck = 0;
    carmap[m_row][m_col]++;
  }
  //take the car off the map and move it
  carmap[m_row][m_col]--;
  old_pos = m_position;
  m_speed += m_max_speed * 0.05f;
  m_speed = MIN (m_speed, m_max_speed);
  m_position += direction[m_direction] * MOVEMENT_SPEED * m_speed;
  //If the car has moved out of view, there's no need to keep simulating it. 
  if (!Visible (glVector ((float)m_row, 0.0f, (float)m_col))) 
    m_ready = false;
  //if the car is far away, remove it.  We use manhattan units because buildings almost always
  //block views of cars on the diagonal.
  if (fabs (camera.x - m_position.x) + fabs (camera.z - m_position.z) > RenderFogDistance ())
    m_ready = false;
  //if the car gets too close to the edge of the map, take it out of play
  if (m_position.x < DEAD_ZONE || m_position.x > (WORLD_SIZE - DEAD_ZONE))
    m_ready = false;
  if (m_position.z < DEAD_ZONE || m_position.z > (WORLD_SIZE - DEAD_ZONE))
    m_ready = false;
  if (m_stuck >= STUCK_TIME)
    m_ready = false;
  if (!m_ready)
    return;
  //Check the new position and make sure its not in another car
  new_row = (int)m_position.x;
  new_col = (int)m_position.z;
  if (new_row != m_row || new_col != m_col) {
    //see if the new position places us on top of another car
    if (carmap[new_row][new_col]) {
      m_position = old_pos;
      m_speed = 0.0f;
      m_stuck++;
    } else {
      //look at the new position and decide if we're heading towards or away from the camera
      m_row = new_row;
      m_col = new_col;
      m_change--;
      m_stuck = 0;
      if (m_direction == NORTH)
        m_front = camera.z < m_position.z;
      else if (m_direction == SOUTH)
        m_front = camera.z > m_position.z;
      else if (m_direction == EAST)
        m_front = camera.x > m_position.x;
      else 
        m_front = camera.x < m_position.x;
    }
  }
  m_drive_position = (m_drive_position + m_position) / 2.0f;
  //place the car back on the map
  carmap[m_row][m_col]++;

}