Full Code of skeeto/pixelcity for AI

master 8e0a90a34ce2 cached
41 files
235.0 KB
63.0k tokens
231 symbols
1 requests
Download .txt
Showing preview only (246K chars total). Download the full file or copy to clipboard to get everything.
Repository: skeeto/pixelcity
Branch: master
Commit: 8e0a90a34ce2
Files: 41
Total size: 235.0 KB

Directory structure:
gitextract_5n_ku7qe/

├── Building.cpp
├── Building.h
├── Camera.cpp
├── Camera.h
├── Car.cpp
├── Car.h
├── Deco.cpp
├── Deco.h
├── Entity.cpp
├── Entity.h
├── Ini.cpp
├── Ini.h
├── Light.cpp
├── Light.h
├── Macro.h
├── Math.cpp
├── Math.h
├── Mesh.cpp
├── Mesh.h
├── PixelCity.dsp
├── Random.cpp
├── Random.h
├── Render.cpp
├── Render.h
├── Sky.cpp
├── Sky.h
├── Texture.cpp
├── Texture.h
├── Visible.cpp
├── Visible.h
├── Win.cpp
├── Win.h
├── World.cpp
├── World.h
├── glBbox.cpp
├── glMatrix.cpp
├── glQuat.cpp
├── glRgba.cpp
├── glTypes.h
├── glVector2.cpp
└── glVector3.cpp

================================================
FILE CONTENTS
================================================

================================================
FILE: Building.cpp
================================================
/*-----------------------------------------------------------------------------

  Building.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This module contains the class to construct the buildings.  

-----------------------------------------------------------------------------*/

#define MAX_VBUFFER         256

#include <windows.h>
#include <math.h>
#include <gl\gl.h>
#include "glTypes.h"

#include "building.h"
#include "deco.h"
#include "light.h"
#include "mesh.h"
#include "macro.h"
#include "math.h"
#include "random.h"
#include "texture.h"
#include "world.h"
#include "win.h"

//This is used by the recursive roof builder to decide what items may be added.
enum
{
  ADDON_NONE,
  ADDON_LOGO,
  ADDON_TRIM,
  ADDON_LIGHTS,
  ADDON_COUNT
};

static GLvector         vector_buffer[MAX_VBUFFER];

/*-----------------------------------------------------------------------------

  This is the constructor for our building constructor.

-----------------------------------------------------------------------------*/

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;
  }

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CBuilding::~CBuilding ()
{

  if (_mesh)
    delete _mesh;
  if (_mesh_flat)
    delete _mesh_flat;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

unsigned CBuilding::Texture ()
{

  return TextureRandomBuilding (_texture_type);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int CBuilding::PolyCount ()
{

  return _mesh->PolyCount () + _mesh_flat->PolyCount ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CBuilding::Render ()
{ 

  glColor3fv (&_color.red);
  _mesh->Render ();

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CBuilding::RenderFlat (bool colored)
{ 

  if (colored)
    glColor3fv (&_color.red);
  _mesh_flat->Render ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

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);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CBuilding::ConstructCube (float left, float right, float front, float back, float bottom, float top)
{

  GLvertex    p[10];
  float       x1, x2, z1, z2, y1, y2;
  int         i;
  cube        c;
  int         base_index;

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

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

}

/*-----------------------------------------------------------------------------

  This will take the given area and populate it with rooftop stuff like
  air conditioners or light towers.

-----------------------------------------------------------------------------*/

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;
  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);
  }
  

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CBuilding::ConstructSpike (int left, int right, int front, int back, int bottom, int top)
{

  GLvertex    p;
  fan         f;
  int         i;
  GLvector    center;

  for (i = 0; i < 5; i++)
    f.index_list.push_back(_mesh_flat->VertexCount () + i);
  f.index_list.push_back(f.index_list[1]);
  p.uv = glVector (0.0f, 0.0f);
  center.x = ((float)left + (float)right) / 2.0f;
  center.z = ((float)front + (float)back) / 2.0f;
  p.position = glVector (center.x, (float)top, center.z);
  _mesh_flat->VertexAdd (p);
 
  p.position = glVector ((float)left, (float)bottom, (float)back);
  _mesh_flat->VertexAdd (p);

  p.position = glVector ((float)right, (float)bottom, (float)back);
  _mesh_flat->VertexAdd (p);

  p.position = glVector ((float)right, (float)bottom, (float)front);
  _mesh_flat->VertexAdd (p);
  
  p.position = glVector ((float)left, (float)bottom, (float)front);
  _mesh_flat->VertexAdd (p);
  
  _mesh_flat->FanAdd (f);

}

/*-----------------------------------------------------------------------------

  This builds an outer wall of a building, with blank (windowless) areas
  deliberately left.  It creates a chain of segments that alternate
  between windowed and windowless, and it always makes sure the wall
  is symetrical.  window_groups tells it how many windows to place in a row.

-----------------------------------------------------------------------------*/

float CBuilding::ConstructWall (int start_x, int start_y, int start_z, int direction, int length, int height, int window_groups, float uv_start, bool blank_corners)
{

  int         x, z;
  int         step_x, step_z;
  int         i;
  quad_strip  qs;
  int         column;
  int         mid;
  int         odd;
  GLvertex    v;
  bool        blank;
  bool        last_blank;

  qs.index_list.reserve(100);

  switch (direction) {
  case NORTH:
    step_z = 1; step_x = 0; break;
  case WEST:
    step_z = 0; step_x = -1; break;
  case SOUTH:
    step_z = -1; step_x = 0; break;
  case EAST:
    step_z = 0; step_x = 1; break;
  }
  x = start_x;;
  z = start_z;
  mid = (length / 2) - 1;
  odd = 1 - (length % 2);
  if (length % 2) 
    mid++;
  //mid = (length / 2);
  v.uv.x = (float)(x + z) / SEGMENTS_PER_TEXTURE;
  v.uv.x = uv_start;
  blank = false;
  for (i = 0; i <= length; i++) {
    //column counts up to the mid point, then back down, to make it symetrical
    if (i <= mid)
      column = i - odd;
    else 
      column = (mid) - (i - (mid));
    last_blank = blank;
    blank = (column % window_groups) > window_groups / 2;
    if (blank_corners && i == 0)
      blank = true;
    if (blank_corners && i == (length - 1))
      blank = true;
    if (last_blank != blank || i == 0 || i == length) {
      v.position = glVector ((float)x, (float)start_y, (float)z);
      v.uv.y = (float)start_y / SEGMENTS_PER_TEXTURE;
      _mesh->VertexAdd (v);
      qs.index_list.push_back(_mesh->VertexCount () - 1);
      v.position.y = (float)(start_y + height);
      v.uv.y = (float)(start_y + height) / SEGMENTS_PER_TEXTURE;;
      _mesh->VertexAdd (v);
      qs.index_list.push_back(_mesh->VertexCount () - 1);
    }
    //if (!blank && i != 0 && i != (length - 1))
    if (!blank && i != length)
      v.uv.x += 1.0f / SEGMENTS_PER_TEXTURE;
    x += step_x;
    z += step_z;
  }
  _mesh->QuadStripAdd (qs);  
  return v.uv.x;

}

/*-----------------------------------------------------------------------------

  This makes a big chunky building of intersecting cubes.  

-----------------------------------------------------------------------------*/

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 ();

}

/*-----------------------------------------------------------------------------

  A single-cube building.  Good for low-rise buildings and stuff that will be 
  far from the camera;

-----------------------------------------------------------------------------*/

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 ();

}


/*-----------------------------------------------------------------------------

  This makes a deformed cylinder building.  

-----------------------------------------------------------------------------*/

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 ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

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 ();

}



================================================
FILE: Building.h
================================================
#ifndef ENTITY
#include "entity.h"
#endif

enum
{
  BUILDING_SIMPLE,
  BUILDING_BLOCKY,
  BUILDING_MODERN,
  BUILDING_TOWER
};

class CBuilding : public CEntity
{
private:

  int                     _x;
  int                     _y;
  int                     _width;
  int                     _depth;
  int                     _height;
  int                     _texture_type;
  int                     _seed;
  int                     _roof_tiers;
  GLrgba                  _color;
  GLrgba                  _trim_color;
  class CMesh*            _mesh;
  class CMesh*            _mesh_flat;
  bool                    _have_lights;
  bool                    _have_trim;
  bool                    _have_logo;


  void                    CreateSimple ();
  void                    CreateBlocky ();
  void                    CreateModern ();
  void                    CreateTower ();
  
  float                   ConstructWall (int start_x, int start_y, int start_z, int direction, int length, int height, int window_groups, float uv_start, bool blank_corners);
  void                    ConstructSpike (int left, int right, int front, int back, int bottom, int top);
  void                    ConstructCube (int left, int right, int front, int back, int bottom, int top);
  void                    ConstructCube (float left, float right, float front, float back, float bottom, float top);
  void                    ConstructRoof (float left, float right, float front, float back, float bottom);

public:
                          CBuilding (int type, int x, int y, int height, int width, int depth, int seed, GLrgba color);
                          ~CBuilding ();
  void                    Render (void);
  int                     PolyCount ();
  void                    RenderFlat (bool colored);
  unsigned                Texture ();

};


================================================
FILE: Camera.cpp
================================================
/*-----------------------------------------------------------------------------

  Camera.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This tracks the position and oritentation of the camera. In screensaver 
  mode, it moves the camera around the world in order to create dramatic 
  views of the hot zone.  

-----------------------------------------------------------------------------*/

#define EYE_HEIGHT              2.0f
#define MAX_PITCH               85
#define FLYCAM_CIRCUT           60000
#define FLYCAM_CIRCUT_HALF      (FLYCAM_CIRCUT / 2)
#define FLYCAM_LEG              (FLYCAM_CIRCUT / 4)
#define ONE_SECOND              1000
#define CAMERA_CHANGE_INTERVAL  15
#define CAMERA_CYCLE_LENGTH     (CAMERA_MODES*CAMERA_CHANGE_INTERVAL)

#include <windows.h>
#include <math.h>
#include <time.h>

#include "glTypes.h"
#include "ini.h"
#include "macro.h"
#include "math.h"
#include "world.h"
#include "win.h"


enum
{
  CAMERA_FLYCAM1,
  CAMERA_ORBIT_INWARD,
  CAMERA_ORBIT_OUTWARD,
  CAMERA_ORBIT_ELLIPTICAL,
  CAMERA_FLYCAM2,
  CAMERA_SPEED,
  CAMERA_SPIN,
  CAMERA_FLYCAM3,
  CAMERA_MODES
};

static GLvector     angle;
static GLvector     position;
static GLvector     auto_angle;
static GLvector     auto_position;
static float        distance;
static GLvector     movement;
static bool         cam_auto;
static float        tracker;
static unsigned     last_update;
static int          camera_behavior;
static unsigned     last_move;

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static GLvector flycam_position (unsigned t)
{

  unsigned    leg;
  float       delta;
  GLvector    start, end;
  GLbbox      hot_zone;

  hot_zone = WorldHotZone ();
  t %= FLYCAM_CIRCUT; 
  leg = t / FLYCAM_LEG;
  delta = (float)(t % FLYCAM_LEG) / FLYCAM_LEG;
  switch (leg) {
  case 0:
    start = glVector (hot_zone.min.x, 25.0f, hot_zone.min.z);
    end = glVector (hot_zone.min.x, 60.0f, hot_zone.max.z);
    break;
  case 1:
    start = glVector (hot_zone.min.x, 60.0f, hot_zone.max.z);
    end = glVector (hot_zone.max.x, 25.0f, hot_zone.max.z);
    break;
  case 2:
    start = glVector (hot_zone.max.x, 25.0f, hot_zone.max.z);
    end = glVector (hot_zone.max.x, 60.0f, hot_zone.min.z);
    break;
  case 3:
    start = glVector (hot_zone.max.x, 60.0f, hot_zone.min.z);
    end = glVector (hot_zone.min.x, 25.0f, hot_zone.min.z);
    break;
  }
  delta = MathScalarCurve (delta);
  return glVectorInterpolate (start, end, delta);


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void do_auto_cam ()
{

  float     dist;
  unsigned  t;
  unsigned  elapsed;
  unsigned  now;
  int       behavior; 
  GLvector  target;

  now = GetTickCount ();
  elapsed = now - last_update;
  elapsed = MIN (elapsed, 50); //limit to 1/20th second worth of time
  if (elapsed == 0)
    return;
  last_update = now;
  t = time (NULL) % CAMERA_CYCLE_LENGTH;
#if SCREENSAVER
  behavior = t / CAMERA_CHANGE_INTERVAL;
#else
  behavior = camera_behavior;
#endif
  tracker += (float)elapsed / 300.0f;
  //behavior = CAMERA_FLYCAM1; 
  switch (behavior) {
  case CAMERA_ORBIT_INWARD:
    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 150.0f;
    auto_position.y = 60.0f;
    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 150.0f;
    target = glVector (WORLD_HALF, 40.0f, WORLD_HALF);
    break;
  case CAMERA_ORBIT_OUTWARD:
    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 250.0f;
    auto_position.y = 60.0f;
    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 250.0f;
    target = glVector (WORLD_HALF, 30.0f, WORLD_HALF);
    break;
  case CAMERA_ORBIT_ELLIPTICAL:
    dist = 150.0f + sinf (tracker * DEGREES_TO_RADIANS / 1.1f) * 50;
    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * dist;
    auto_position.y = 60.0f;
    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * dist;
    target = glVector (WORLD_HALF, 50.0f, WORLD_HALF);
    break;
  case CAMERA_FLYCAM1:
  case CAMERA_FLYCAM2:
  case CAMERA_FLYCAM3:
    auto_position = (flycam_position (now) + flycam_position (now + 4000)) / 2.0f;
    target = flycam_position (now + FLYCAM_CIRCUT_HALF - ONE_SECOND * 3);
    break;
  case CAMERA_SPEED:
    auto_position = (flycam_position (now) + flycam_position (now + 500)) / 2.0f;
    target = flycam_position (now + ONE_SECOND * 5);
    auto_position.y /= 2;
    target.y /= 2;
    break;
  case CAMERA_SPIN:
  default:  
    target.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 300.0f;
    target.y = 30.0f;
    target.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 300.0f;
    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 50.0f;
    auto_position.y = 60.0f;
    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 50.0f;
  }
  dist = MathDistance (auto_position.x, auto_position.z, target.x, target.z);
  auto_angle.y = MathAngle (-MathAngle (auto_position.x, auto_position.z, target.x, target.z));
  auto_angle.x = 90.0f + MathAngle (0, auto_position.y, dist, target.y);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraAutoToggle ()
{

  cam_auto = !cam_auto;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraNextBehavior ()
{

  camera_behavior++;
  camera_behavior %= CAMERA_MODES;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraYaw (float delta)
{

  angle.y -= delta;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraPitch (float delta)
{

  angle.x -= delta;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraPan (float delta)
{

  float           move_x, move_y;

  move_x = (float)sin (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
  move_y = (float)cos (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
  position.x -= move_y * delta;
  position.z -= -move_x * delta;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraForward (float delta)
{

  float           move_x, move_y;

  move_y = (float)sin (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
  move_x = (float)cos (-angle.y * DEGREES_TO_RADIANS) / 10.0f;
  position.x -= move_y * delta;
  position.z -= move_x * delta;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraVertical (float val)
{

  movement.y += val;
  last_move = GetTickCount ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraLateral (float val)
{

  movement.x += val;
  last_move = GetTickCount ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraMedial (float val)
{

  movement.z += val;
  last_move = GetTickCount ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

GLvector CameraPosition (void)		
{
 
  if (cam_auto)
    return auto_position;
  return position;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraReset ()		
{

  position.y = 50.0f;
  position.x = WORLD_HALF;
  position.z = WORLD_HALF;
  angle.x = 0.0f;
  angle.y = 0.0f;
  angle.z = 0.0f;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraPositionSet (GLvector new_pos)		
{

  position = new_pos;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

GLvector CameraAngle (void)		
{

  if (cam_auto)
    return auto_angle;
  return angle;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraAngleSet (GLvector new_angle)		
{

  angle = new_angle;
  angle.x = CLAMP (angle.x, -80.0f, 80.0f);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraInit (void)		
{

  angle = IniVector ("CameraAngle");
  position = IniVector ("CameraPosition");

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraUpdate (void)		
{

  CameraPan (movement.x);
  CameraForward (movement.z);
  position.y += movement.y / 10.0f;
  if (GetTickCount () - last_move > 1000)
    movement *= 0.9f;
  else
    movement *= 0.99f;
  if (SCREENSAVER)
    cam_auto = true;
  if (cam_auto) 
    do_auto_cam ();
  if (angle.y < 0.0f) 
    angle.y = 360.0f - (float)fmod (fabs (angle.y), 360.0f);
  angle.y = (float)fmod (angle.y, 360.0f);
  angle.x = CLAMP (angle.x, -MAX_PITCH, MAX_PITCH);
 
}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CameraTerm (void)		
{

  //just store our most recent position in the ini
  IniVectorSet ("CameraAngle", angle);
  IniVectorSet ("CameraPosition", position);
 
}


================================================
FILE: Camera.h
================================================
#ifndef TYPES
#include "glTypes.h"
#endif

GLvector  CameraAngle (void);
void      CameraAngleSet (GLvector new_angle);
void      CameraAutoToggle ();
float     CameraDistance (void);
void      CameraDistanceSet (float new_distance);
void      CameraInit (void);
void      CameraNextBehavior (void);
GLvector  CameraPosition (void);
void      CameraPositionSet (GLvector new_pos);
void      CameraReset ();
void      CameraUpdate (void);	
void      CameraTerm (void);

void      CameraForward (float delta);
void      CameraPan (float delta_x);
void      CameraPitch (float delta_y);
void      CameraYaw (float delta_x);
void      CameraVertical (float val);
void      CameraLateral (float val);
void      CameraMedial (float val);

================================================
FILE: Car.cpp
================================================
/*-----------------------------------------------------------------------------

  Car.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This creates the little two-triangle cars and moves them around the map.

-----------------------------------------------------------------------------*/

#define DEAD_ZONE       200
#define STUCK_TIME      230
#define UPDATE_INTERVAL 50 //milliseconds
#define MOVEMENT_SPEED  0.61f
#define CAR_SIZE        3.0f

#include <windows.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "glTypes.h"

#include "building.h"
#include "car.h"
#include "camera.h"
#include "mesh.h"
#include "macro.h"
#include "math.h"
#include "random.h"
#include "render.h"
#include "texture.h"
#include "world.h"
#include "visible.h"
#include "win.h"

static GLvector           direction[] = 
{
  0.0f, 0.0f, -1.0f,
  1.0f, 0.0f,  0.0f,
  0.0f, 0.0f,  1.0f,
 -1.0f, 0.0f,  0.0f,
};

static int                dangles[] = { 0, 90, 180, 270};

static GLvector2          angles[360];
static bool               angles_done;
static unsigned char      carmap[WORLD_SIZE][WORLD_SIZE];
static CCar*              head;
static unsigned           next_update;
static int                count;

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int CarCount ()
{

  return count;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CarClear ()
{

  CCar*       c;

  for (c = head; c; c = c->m_next)
    c->Park ();
  ZeroMemory (carmap, sizeof (carmap));
  count = 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CarRender ()
{

  CCar*       c;

  if (!angles_done) {
    for (int i = 0 ;i < 360; i++) {
      angles[i].x = cosf ((float)i * DEGREES_TO_RADIANS) * CAR_SIZE;
      angles[i].y = sinf ((float)i * DEGREES_TO_RADIANS) * CAR_SIZE;
    }
  }
  glDepthMask (false);
  glEnable (GL_BLEND);
  glDisable (GL_CULL_FACE);
  glBlendFunc (GL_ONE, GL_ONE);
  glBindTexture (GL_TEXTURE_2D, 0);
  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_HEADLIGHT));
  for (c = head; c; c = c->m_next)
    c->Render ();
  glDepthMask (true);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CarUpdate ()
{

  CCar*       c;
  unsigned    now;

  if (!TextureReady () || !EntityReady ())
    return;
  now = GetTickCount ();
  if (next_update > now)
    return;
  next_update = now + UPDATE_INTERVAL;
  for (c = head; c; c = c->m_next)
    c->Update ();

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CCar::CCar ()
{

  m_ready = false;
  m_next = head;
  head = this;
  count++;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool CCar::TestPosition (int row, int col)
{

  //test the given position and see if it's already occupied
  if (carmap[row][col])
    return false;
  //now make sure that the lane is going the right direction
  if (WorldCell (row, col) != WorldCell (m_row, m_col))
    return false;
  return true;

}
 
/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

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]++;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CCar::Render ()
{

  GLvector  pos;
  int       angle;
  int       turn;
  float     top;

  if (!m_ready)
    return;
  if (!Visible (m_drive_position))
    return;
  if (m_front) {
    glColor3f (1, 1, 0.8f);
    top = CAR_SIZE;
  } else {
    glColor3f (0.5, 0.2f, 0);
    top = 0.0f;
  }

  glBegin (GL_QUADS);

  angle = dangles[m_direction];
  pos = m_drive_position;// 
  angle = 360 - (int)MathAngle (m_position.x, m_position.z, pos.x, pos.z);
  angle %= 360;
  turn = (int)MathAngleDifference ((float)m_drive_angle, (float)angle);
  m_drive_angle += SIGN (turn);
  pos += glVector (0.5f, 0.0f, 0.5f);
  
  glTexCoord2f (0, 0);   
  glVertex3f (pos.x + angles[angle].x, -CAR_SIZE, pos.z + angles[angle].y);
  glTexCoord2f (1, 0);   
  glVertex3f (pos.x - angles[angle].x, -CAR_SIZE, pos.z - angles[angle].y);
  glTexCoord2f (1, 1);   
  glVertex3f (pos.x - angles[angle].x,  top, pos.z - angles[angle].y);
  glTexCoord2f (0, 1);   
  glVertex3f (pos.x + angles[angle].x,  top, pos.z +  angles[angle].y);
  
  glEnd ();

}

================================================
FILE: Car.h
================================================
class CCar
{
  GLvector        m_position;
  GLvector        m_drive_position;
  bool            m_ready;
  bool            m_front;
  int             m_drive_angle;
  int             m_row;
  int             m_col;
  int             m_direction;
  int             m_change;
  int             m_stuck;
  float           m_speed;
  float           m_max_speed;

public:
                  CCar ();
  bool            TestPosition (int row, int col);
  void            Render ();
  void            Update ();
  void            Park () { m_ready = false;}
  class CCar*     m_next;

};

void  CarClear ();
int   CarCount ();
void  CarRender ();
void  CarUpdate ();



================================================
FILE: Deco.cpp
================================================
/*-----------------------------------------------------------------------------

  Deco.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This handles building and rendering decoration objects - infrastructure & 
  such around the city.

-----------------------------------------------------------------------------*/

#define LOGO_OFFSET           0.2f //How far a logo sticks out from the given surface

#include <windows.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "glTypes.h"

#include "deco.h"
#include "light.h"
#include "mesh.h"
#include "macro.h"
#include "math.h"
#include "random.h"
#include "render.h"
#include "texture.h"
#include "world.h"
#include "visible.h"


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CDeco::~CDeco ()
{

  delete _mesh;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CDeco::CDeco ()
{

  _mesh = new CMesh ();
  _use_alpha = false;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CDeco::Render ()
{

  glColor3fv (&_color.red);
  _mesh->Render ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CDeco::RenderFlat (bool colored)
{


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool CDeco::Alpha ()
{ 
  
  return _use_alpha; 

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int CDeco::PolyCount ()
{

  return _mesh->PolyCount ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

unsigned CDeco::Texture ()
{

  return _texture;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CDeco::CreateRadioTower (GLvector pos, float height)
{

  CLight*   l;
  float     offset;
  GLvertex  v;
  fan       f;

  for(int i=0; i<6; i++)
    f.index_list.push_back(i);

  offset = height / 15.0f;
  _center = pos;
  _use_alpha = true;
  //Radio tower
  v.position = glVector (_center.x, _center.y + height, _center.z);  v.uv = glVector (0,1);
  _mesh->VertexAdd (v);
  v.position = glVector (_center.x - offset, _center.y, _center.z - offset);  v.uv = glVector (1,0);
  _mesh->VertexAdd (v);
  v.position = glVector (_center.x + offset, _center.y, _center.z - offset);  v.uv = glVector (0,0);
  _mesh->VertexAdd (v);
  v.position = glVector (_center.x + offset, _center.y, _center.z + offset);  v.uv = glVector (1,0);
  _mesh->VertexAdd (v);
  v.position = glVector (_center.x - offset, _center.y, _center.z + offset);  v.uv = glVector (0,0);
  _mesh->VertexAdd (v);
  v.position = glVector (_center.x - offset, _center.y, _center.z - offset);  v.uv = glVector (1,0);
  _mesh->VertexAdd (v);
  _mesh->FanAdd (f);
  l = new CLight (glVector (_center.x, _center.y + height + 1.0f, _center.z), glRgba (255,192,160), 1);
  l->Blink ();
  _texture = TextureId (TEXTURE_LATTICE);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CDeco::CreateLogo (GLvector2 start, GLvector2 end, float bottom, int seed, GLrgba color)
{

  GLvertex   p;
  quad_strip qs;
  float      u1, u2, v1, v2;
  float      top;
  float      height, length;
  GLvector2  center2d;
  GLvector   to;
  GLvector   out;
  int        logo_index;

  qs.index_list.push_back(0);
  qs.index_list.push_back(1);
  qs.index_list.push_back(3);
  qs.index_list.push_back(2);

  _use_alpha = true;
  _color = color;
  logo_index = seed % LOGO_ROWS;
  to = glVector (start.x, 0.0f, start.y) - glVector (end.x, 0.0f, end.y);
  to = glVectorNormalize (to);
  out = glVectorCrossProduct (glVector (0.0f, 1.0f, 0.0f), to) * LOGO_OFFSET;
  center2d = (start + end) / 2;
  _center = glVector (center2d.x, bottom, center2d.y);
  length = glVectorLength (start - end);
  height = (length / 8.0f) * 1.5f;
  top = bottom + height;
  u1 = 0.0f;
  u2 = 0.5f;//We actually only use the left half of the texture
  v1 = (float)logo_index / LOGO_ROWS;
  v2 = v1 + (1.0f / LOGO_ROWS);
  p.position = glVector (start.x, bottom, start.y) + out;  p.uv = glVector (u1,v1);
  _mesh->VertexAdd (p);
  p.position = glVector (end.x, bottom, end.y) + out;  p.uv = glVector (u2, v1);
  _mesh->VertexAdd (p);
  p.position = glVector (end.x, top, end.y) + out;  p.uv = glVector (u2, v2);
  _mesh->VertexAdd (p);
  p.position = glVector (start.x, top, start.y) + out;  p.uv = glVector (u1, v2);
  _mesh->VertexAdd (p);
  _mesh->QuadStripAdd (qs);
  _texture = TextureId (TEXTURE_LOGOS);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CDeco::CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color)
{

  GLvertex   p;
  quad_strip qs1;
  float      u, v;
  
  qs1.index_list.push_back(0);
  qs1.index_list.push_back(1);
  qs1.index_list.push_back(3);
  qs1.index_list.push_back(2);
  _color = color;
  _use_alpha = true;
  _center = glVector (x + width / 2, height, z + depth / 2);
  if (width < depth) {
    u = 1.0f;
    v = (float)((int)(depth / width));
  } else {
    v = 1.0f;
    u = (float)((int)(width / depth));
  }
  _texture = TextureId (TEXTURE_LIGHT);
  p.position = glVector (x, height, z);  p.uv = glVector (0.0f, 0.0f);
  _mesh->VertexAdd (p);
  p.position = glVector (x, height, z + depth);  p.uv = glVector (0.0f, v);
  _mesh->VertexAdd (p);
  p.position = glVector (x + width, height, z + depth);  p.uv = glVector (u, v);
  _mesh->VertexAdd (p);
  p.position = glVector (x + width, height, z);  p.uv = glVector (u, 0.0f);
  _mesh->VertexAdd (p);
  _mesh->QuadStripAdd (qs1);
  _mesh->Compile ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CDeco::CreateLightTrim (GLvector* chain, int count, float height, int seed, GLrgba color)
{

  GLvertex   p;
  GLvector   to;
  GLvector   out;
  int        i;
  int        index;
  int        prev, next;
  float      u, v1, v2;
  float      row;
  quad_strip qs;

  _color = color;
  _center = glVector (0.0f, 0.0f, 0.0f);
  qs.index_list.reserve(count * 2 + 2);
  for (i = 0; i < count; i++) 
    _center += chain[i];
  _center /= (float)count;
  row = (float)(seed % TRIM_ROWS);
  v1 = row * TRIM_SIZE;
  v2 = (row + 1.0f) * TRIM_SIZE;
  index = 0;
  u = 0.0f;
  for (i = 0; i < count + 1; i++) {
    if (i)
      u += glVectorLength (chain[i % count] - p.position) * 0.1f;
    //Add the bottom point      
    prev = i - 1;
    if (prev < 0)
      prev = count + prev;
    next = (i + 1) % count;
    to = glVectorNormalize (chain[next] - chain[prev]);
    out = glVectorCrossProduct (glVector (0.0f, 1.0f, 0.0f), to) * LOGO_OFFSET;
    p.position = chain[i % count] + out; p.uv = glVector (u, v2);
    _mesh->VertexAdd (p);
    qs.index_list.push_back(index++);
    //Top point
    p.position.y += height;p.uv = glVector (u, v1);
    _mesh->VertexAdd (p);
    qs.index_list.push_back(index++);
  }
  _mesh->QuadStripAdd (qs);
  _texture = TextureId (TEXTURE_TRIM);
  _mesh->Compile ();

}

================================================
FILE: Deco.h
================================================
#ifndef ENTITY
#include "entity.h"
#endif

class CDeco : CEntity
{
  GLrgba        _color;
  class CMesh*  _mesh;
  int           _type;
  unsigned      _texture;
  bool          _use_alpha;

public:

                CDeco ();
                ~CDeco ();
  void          CreateLogo (GLvector2 start, GLvector2 end, float base, int seed, GLrgba color);
  void          CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color);
  void          CreateLightTrim (GLvector* chain, int count, float height, int seed, GLrgba color);
  void          CreateRadioTower (GLvector pos, float height);
  void          Render (void);
  void          RenderFlat (bool colored);
  bool          Alpha ();
  int           PolyCount ();

  unsigned      Texture ();

};

================================================
FILE: Entity.cpp
================================================
/*-----------------------------------------------------------------------------

  Entity.cpp

  Copyright (c) 2005 Shamus Young
  All Rights Reserved

-------------------------------------------------------------------------------

  An entity is any renderable stationary object in the world.  This is an 
  abstract class.  This module gathers up the Entities, sorts them by 
  texture use and location, and then stores them in OpenGL render lists
  for faster rendering.    

-----------------------------------------------------------------------------*/

#include <windows.h>
#include <math.h>
#include <gl\gl.h>

#include "camera.h"
#include "entity.h"
#include "macro.h"
#include "math.h"
#include "render.h"
#include "texture.h"
#include "world.h"
#include "visible.h"
#include "win.h"

struct entity
{
  CEntity*            object;
};


struct cell
{
  unsigned        list_textured;
  unsigned        list_flat;
  unsigned        list_flat_wireframe;
  unsigned        list_alpha;
  GLvector        pos;
};

static cell           cell_list[GRID_SIZE][GRID_SIZE];
static int            entity_count;
static entity*        entity_list;
static bool           sorted;
static bool           compiled;
static int            polycount;
static int            compile_x;
static int            compile_y;
static int            compile_count;
static int            compile_end;

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static int do_compare (const void *arg1, const void *arg2 )
{

  struct entity*  e1 = (struct entity*)arg1;
  struct entity*  e2 = (struct entity*)arg2;

  if (e1->object->Alpha () && !e2->object->Alpha ())
    return 1;
  if (!e1->object->Alpha () && e2->object->Alpha ())
    return -1;
  if (e1->object->Texture () > e2->object->Texture ())
    return 1;
  else if (e1->object->Texture () < e2->object->Texture ())
    return -1;
  return 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void add (CEntity* b)
{

  entity_list = (entity*)realloc (entity_list, sizeof (entity) * (entity_count + 1));
  entity_list[entity_count].object = b;
  entity_count++;
  polycount = 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void do_compile ()
{

  int       i;
  int       x, y;

  if (compiled)
    return;
  x = compile_x;
  y = compile_y;
  //Changing textures is pretty expensive, and thus sorting the entites so that
  //they are grouped by texture used can really improve framerate.
  //qsort (entity_list, entity_count, sizeof (struct entity), do_compare);
  //sorted = true;
  //Now group entites on the grid 
  //make a list for the textured objects in this region
  if (!cell_list[x][y].list_textured)
    cell_list[x][y].list_textured = glGenLists(1);
  glNewList (cell_list[x][y].list_textured, GL_COMPILE);
  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
  for (i = 0; i < entity_count; i++) {
    GLvector pos = entity_list[i].object->Center ();
    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {
      glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());
      entity_list[i].object->Render ();
    }
  }
  glEndList();	

  //Make a list of flat-color stuff (A/C units, ledges, roofs, etc.)
  if (!cell_list[x][y].list_flat)
    cell_list[x][y].list_flat = glGenLists(1);
  glNewList (cell_list[x][y].list_flat, GL_COMPILE);
  glEnable (GL_CULL_FACE);
  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
  for (i = 0; i < entity_count; i++) {
    GLvector pos = entity_list[i].object->Center ();
    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {
      entity_list[i].object->RenderFlat (false);
    }
  }
  glEndList();	
  //Now a list of flat-colored stuff that will be wireframe friendly
  if (!cell_list[x][y].list_flat_wireframe)
    cell_list[x][y].list_flat_wireframe = glGenLists(1);
  glNewList (cell_list[x][y].list_flat_wireframe, GL_COMPILE);
  glEnable (GL_CULL_FACE);
  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
  for (i = 0; i < entity_count; i++) {
    GLvector pos = entity_list[i].object->Center ();
    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {
      entity_list[i].object->RenderFlat (true);
    }
  }
  glEndList();	
  //Now a list of stuff to be alpha-blended, and thus rendered last
  if (!cell_list[x][y].list_alpha)
    cell_list[x][y].list_alpha = glGenLists(1);
  glNewList (cell_list[x][y].list_alpha, GL_COMPILE);
  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);
  glDepthMask (false);
  glEnable (GL_BLEND);
  glDisable (GL_CULL_FACE);
  for (i = 0; i < entity_count; i++) {
    GLvector pos = entity_list[i].object->Center ();
    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && entity_list[i].object->Alpha ()) {
      glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());
      entity_list[i].object->Render ();
    }
  }
  glDepthMask (true);
  glEndList();	

  //now walk the grid
  compile_x++;
  if (compile_x == GRID_SIZE) {
    compile_x = 0;
    compile_y++;
    if (compile_y == GRID_SIZE)
      compiled = true;
    compile_end = GetTickCount ();
  } 
  compile_count++;


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool EntityReady ()
{

  return compiled;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

float EntityProgress ()
{

  return (float)compile_count / (GRID_SIZE * GRID_SIZE);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void EntityUpdate ()
{

  unsigned    stop_time;

  if (!TextureReady ()) {
    sorted = false;
    return;
  } 
  if (!sorted) {
    qsort (entity_list, entity_count, sizeof (struct entity), do_compare);
    sorted = true;
  }
  //We want to do several cells at once. Enough to get things done, but
  //not so many that the program is unresponsive.
  if (LOADING_SCREEN) {  //If we're using a loading screen, we want to build as fast as possible
    stop_time = GetTickCount () + 100;
    while (!compiled && GetTickCount () < stop_time)
      do_compile ();
  } else //Take it slow
    do_compile ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void EntityRender ()
{

  int       polymode[2];
  bool      wireframe;
  int       x, y;
  int       elapsed;

  //Draw all textured objects
  glGetIntegerv (GL_POLYGON_MODE, &polymode[0]);
  wireframe = polymode[0] != GL_FILL;
  if (RenderFlat ())
    glDisable (GL_TEXTURE_2D);
  //If we're not using a loading screen, make the wireframe fade out via fog
  if (!LOADING_SCREEN && wireframe) {
    elapsed = 6000 - WorldSceneElapsed ();
    if (elapsed >= 0 && elapsed <= 6000)
      RenderFogFX ((float)elapsed / 6000.0f);
    else
      return;
  }
  for (x = 0; x < GRID_SIZE; x++) {
    for (y = 0; y < GRID_SIZE; y++) {
      if (Visible (x,y))
        glCallList (cell_list[x][y].list_textured);
    }
  }
  //draw all flat colored objects
  glBindTexture(GL_TEXTURE_2D, 0);
  glColor3f (0, 0, 0);
  for (x = 0; x < GRID_SIZE; x++) {
    for (y = 0; y < GRID_SIZE; y++) {
      if (Visible (x, y)) {
        if (wireframe)
          glCallList (cell_list[x][y].list_flat_wireframe);
        else 
          glCallList (cell_list[x][y].list_flat);
      }
    }
  }
  //draw all alpha-blended objects
  glBindTexture(GL_TEXTURE_2D, 0);
  glColor3f (0, 0, 0);
  glEnable (GL_BLEND);
  for (x = 0; x < GRID_SIZE; x++) {
    for (y = 0; y < GRID_SIZE; y++) {
      if (Visible (x,y)) {
        glCallList (cell_list[x][y].list_alpha);
      }
    }
  }
  
}




/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void EntityClear ()
{

  for (int i = 0; i < entity_count; i++) {
    delete entity_list[i].object;
  }
  if (entity_list)
    free (entity_list);
  entity_list = NULL;
  entity_count = 0;
  compile_x = 0;
  compile_y = 0;
  compile_count = 0;
  compiled = false;
  sorted = false;

  int  x, y;

  for (x = 0; x < GRID_SIZE; x++) {
    for (y = 0; y < GRID_SIZE; y++) {
      glNewList (cell_list[x][y].list_textured, GL_COMPILE);
      glEndList();	
      glNewList (cell_list[x][y].list_alpha, GL_COMPILE);
      glEndList();	
      glNewList (cell_list[x][y].list_flat_wireframe, GL_COMPILE);
      glEndList();	
      glNewList (cell_list[x][y].list_flat, GL_COMPILE);
      glEndList();	
    }
  }


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int EntityCount ()
{

  return entity_count;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void EntityInit (void)
{

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int EntityPolyCount (void)
{

  if (!sorted)
    return 0;
  if (polycount)
    return polycount;
  for (int i = 0; i < entity_count; i++) 
    polycount += entity_list[i].object->PolyCount ();
  return polycount;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CEntity::CEntity (void)
{

  add (this);

}

void CEntity::Render (void)
{

}

void CEntity::RenderFlat (bool wireframe)
{

}

void CEntity::Update (void)
{


}




================================================
FILE: Entity.h
================================================
#ifndef TYPES
#include "glTypes.h"
#endif

#ifndef ENTITY

#define ENTITY

class CEntity
{
private:
protected:

  GLvector                _center;

public:
                          CEntity (void);
  virtual                 ~CEntity () {};
  virtual void            Render (void);
  virtual void            RenderFlat (bool wirefame);
  virtual unsigned        Texture () { return 0; }
  virtual void            Update (void);
  virtual bool            Alpha () { return false; }
  virtual int             PolyCount () { return 0; }
  GLvector                Center () { return _center; }

};

void      EntityClear ();
int       EntityCount (void);
float     EntityProgress ();
bool      EntityReady ();
void      EntityRender (void);
void      EntityUpdate (void);
int       EntityPolyCount (void);

#endif

================================================
FILE: Ini.cpp
================================================
/*-----------------------------------------------------------------------------

  Ini.cpp

  2009 Shamus Young


-------------------------------------------------------------------------------
  
  This takes various types of data and dumps them into a predefined ini file.

-----------------------------------------------------------------------------*/

#define FORMAT_VECTOR       "%f %f %f"
#define MAX_RESULT          256
#define FORMAT_FLOAT        "%1.2f"
#define INI_FILE            ".\\" APP ".ini"
#define SECTION             "Settings"

#include <windows.h>
#include <stdio.h>
#include "glTypes.h"

#include "ini.h"
#include "win.h"

static char                 result[MAX_RESULT];

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int IniInt (char* entry)
{

  int         result;

  result = GetPrivateProfileInt (SECTION, entry, 0, INI_FILE);
  return result;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void IniIntSet (char* entry, int val)
{

  char        buf[20];

  sprintf (buf, "%d", val);
  WritePrivateProfileString (SECTION, entry, buf, INI_FILE);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

float IniFloat (char* entry)
{

  float     f;

  GetPrivateProfileString (SECTION, entry, "", result, MAX_RESULT, INI_FILE);
  f = (float)atof (result);
  return f;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void IniFloatSet (char* entry, float val)
{

  char        buf[20];
  
  sprintf (buf, FORMAT_FLOAT, val);
  WritePrivateProfileString (SECTION, entry, buf, INI_FILE);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

char* IniString (char* entry)
{

  GetPrivateProfileString (SECTION, entry, "", result, MAX_RESULT, INI_FILE);
  return result;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void IniStringSet (char* entry, char* val)
{

  WritePrivateProfileString (SECTION, entry, val, INI_FILE);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void IniVectorSet (char* entry, GLvector v)
{
  
  sprintf (result, FORMAT_VECTOR, v.x, v.y, v.z);
  WritePrivateProfileString (SECTION, entry, result, INI_FILE);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

GLvector IniVector (char* entry)
{

  GLvector  v;

  v.x = v.y = v.z = 0.0f;
  GetPrivateProfileString (SECTION, entry, "0 0 0", result, MAX_RESULT, INI_FILE);
  sscanf (result, FORMAT_VECTOR, &v.x, &v.y, &v.z);
  return v;

}


================================================
FILE: Ini.h
================================================
int       IniInt (char* entry);
void      IniIntSet (char* entry, int val);
float     IniFloat (char* entry);
void      IniFloatSet (char* entry, float val);
char*     IniString (char* entry);
void      IniStringSet (char* entry, char* val);
void      IniVectorSet (char* entry, GLvector v);
GLvector  IniVector (char* entry);


================================================
FILE: Light.cpp
================================================
/*-----------------------------------------------------------------------------

  Light.cpp

  2006 Shamus Young

-------------------------------------------------------------------------------

  This tracks and renders the light sources. (Note that they do not really 
  CAST light in the OpenGL sense of the world, these are just simple panels.) 
  These are NOT subclassed to entities because these are dynamic.  Some lights 
  blink, and thus they can't go into the fixed render lists managed by 
  Entity.cpp.  

-----------------------------------------------------------------------------*/

#define MAX_SIZE            5

#include <windows.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include "glTypes.h"

#include "camera.h"
#include "entity.h"
#include "light.h"
#include "macro.h"
#include "math.h"
#include "random.h"
#include "render.h"
#include "texture.h"
#include "visible.h"

static GLvector2      angles[5][360];
static CLight*        head;
static bool           angles_done;
static int            count;

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void LightClear ()
{

  CLight*   l;

  while (head) {
    l = head;
    head = l->_next;
    delete l;
  }
  count = 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int LightCount ()
{

  return count;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void LightRender ()
{

  CLight*     l;

  if (!EntityReady ())
    return;
  if (!angles_done) {
    for (int size = 0; size < MAX_SIZE; size++) {
      for (int i = 0 ;i < 360; i++) {
        angles[size][i].x = cosf ((float)i * DEGREES_TO_RADIANS) * ((float)size + 0.5f);
        angles[size][i].y = sinf ((float)i * DEGREES_TO_RADIANS) * ((float)size + 0.5f);
      }
    }
  }
  glDepthMask (false);
  glEnable (GL_BLEND);
  glDisable (GL_CULL_FACE);
  glBlendFunc (GL_ONE, GL_ONE);
  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_LIGHT));
  glDisable (GL_CULL_FACE);
  glBegin (GL_QUADS);
  for (l = head; l; l = l->_next) 
    l->Render ();
  glEnd ();
  glDepthMask (true);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CLight::CLight (GLvector pos, GLrgba color, int size)
{

  _position = pos;
  _color = color;
  _size = CLAMP (size, 0, (MAX_SIZE - 1));
  _vert_size = (float)_size + 0.5f;
  _flat_size = _vert_size + 0.5f;
  _blink = false;
  _cell_x = WORLD_TO_GRID(pos.x);
  _cell_z = WORLD_TO_GRID(pos.z);
  _next = head;
  head = this;
  count++;


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

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);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CLight::Render ()
{

  int       angle;
  GLvector  pos;
  GLvector  camera;
  GLvector  camera_position;
  GLvector2 offset;

  if (!Visible (_cell_x, _cell_z))
    return;
  camera = CameraAngle ();
  camera_position = CameraPosition ();
  if (fabs (camera_position.x - _position.x) > RenderFogDistance ())
    return;
  if (fabs (camera_position.z - _position.z) > RenderFogDistance ())
    return;
  if (_blink && (GetTickCount () % _blink_interval) > 200)
    return;
  angle = (int)MathAngle (camera.y);
  offset = angles[_size][angle];
  pos = _position;
  glColor4fv (&_color.red);
  glTexCoord2f (0, 0);   
  glVertex3f (pos.x + offset.x, pos.y - _vert_size, pos.z + offset.y);
  glTexCoord2f (0, 1);   
  glVertex3f (pos.x - offset.x, pos.y - _vert_size, pos.z - offset.y);
  glTexCoord2f (1, 1);   
  glVertex3f (pos.x - offset.x, pos.y + _vert_size, pos.z - offset.y);
  glTexCoord2f (1, 0);   
  glVertex3f (pos.x + offset.x, pos.y + _vert_size, pos.z + offset.y);

}

================================================
FILE: Light.h
================================================
class CLight
{
  GLvector        _position;
  GLrgba          _color;
  int             _size;
  float           _vert_size;
  float           _flat_size;
  bool            _blink;
  unsigned        _blink_interval;
  int             _cell_x;
  int             _cell_z;

public:
                  CLight(GLvector pos, GLrgba color, int size);
  class CLight*   _next;
  void            Render ();
  void            Blink ();

};

void  LightRender ();
void  LightClear ();
int   LightCount ();


================================================
FILE: Macro.h
================================================
#define LIMIT_INTERVAL(interval)  { static unsigned next_update; if (next_update > GetTickCount ()) return; next_update = GetTickCount () + interval;}
#define DEGREES_TO_RADIANS        .017453292F
#define RADIANS_TO_DEGREES        57.29577951F
#define PI                        ((double)3.1415926535F)
#define PI2                       PI*PI
#define GRAVITY                   9.5f
#define CLAMP(a,b,c)              (a < b ? b : (a > c ? c : a))
#define WRAP(x,y)                 ((unsigned)x % y)
#define SIGN(x)                   (((x) > 0) ? 1 : ((x) < 0) ? -1 : 0)
#define ABS(x)                    (((x) < 0 ? (-x) : (x)))
#define SMALLEST(x,y)             (ABS(x) < ABS(y) ? 0 : x)                
#define MIN(x,y)                  ((x) < (y) ? x : y)                
#define MAX(x,y)                  ((x) > (y) ? x : y)                
#define POW(x,y)                  (float)pow(x,y)
#define SWAP(a,b)                 {int temp = a;a = b; b = temp;}


================================================
FILE: Math.cpp
================================================
/*-----------------------------------------------------------------------------

  Math.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------
  
  Various useful math functions.

-----------------------------------------------------------------------------*/

#include <math.h>

#include "macro.h"
#include "math.h"

/*-----------------------------------------------------------------------------
Keep an angle between 0 and 360
-----------------------------------------------------------------------------*/

float MathAngle (float angle)
{

  if (angle < 0.0f) 
    angle = 360.0f - (float)fmod (fabs (angle), 360.0f);
  else
    angle = (float)fmod (angle, 360.0f);
  return angle;

}

/*-----------------------------------------------------------------------------
Get an angle between two given points on a grid
-----------------------------------------------------------------------------*/

float MathAngle (float x1, float y1, float x2, float y2)
{

  float   x_delta;
  float   z_delta;
  float   angle;

  z_delta = (y1 - y2);
  x_delta = (x1 - x2); 
  if (x_delta == 0) {
    if (z_delta > 0)
      return 0.0f;
    else
      return 180.0f;
  }
  if (fabs (x_delta) < fabs (z_delta)) {
    angle = 90 - (float)atan (z_delta / x_delta) * RADIANS_TO_DEGREES;
    if (x_delta < 0)
      angle -= 180.0f;
  } else {
    angle = (float)atan (x_delta / z_delta) * RADIANS_TO_DEGREES;
    if (z_delta < 0.0f)
      angle += 180.0f;
  }
  if (angle< 0.0f)
    angle += 360.0f;
  return angle;

}

/*-----------------------------------------------------------------------------
Get distance (squared) between 2 points on a plane
-----------------------------------------------------------------------------*/

float MathDistance2 (float x1, float y1, float x2, float y2)
{

  float     dx;
  float     dy;

  dx = x1 - x2;
  dy = y1 - y2;
  return dx * dx + dy * dy;

}

/*-----------------------------------------------------------------------------
Get distance between 2 points on a plane. This is slightly slower than 
MathDistance2 ()
-----------------------------------------------------------------------------*/

float MathDistance (float x1, float y1, float x2, float y2)
{

  float     dx;
  float     dy;

  dx = x1 - x2;
  dy = y1 - y2;
  return (float)sqrt (dx * dx + dy * dy);

}

/*-----------------------------------------------------------------------------
difference between two angles
-----------------------------------------------------------------------------*/

float MathAngleDifference (float a1, float a2)

{

  float         result;

  result = (float)fmod (a1 - a2, 360.0f);
  if (result > 180.0)
    return result - 360.0F;
  if (result < -180.0)
    return result + 360.0F;
  return result;

}

/*-----------------------------------------------------------------------------
interpolate between two values
-----------------------------------------------------------------------------*/

float MathInterpolate (float n1, float n2, float delta)
{

  return n1 * (1.0f - delta) + n2 * delta;

}

/*-----------------------------------------------------------------------------
return a scalar of 0.0 to 1.0, based an the given values position within a range
-----------------------------------------------------------------------------*/

float MathSmoothStep (float val, float a, float b)
{

  if (b == a)
    return 0.0f;
  val -= a;
  val /= (b - a);
  return CLAMP (val, 0.0f, 1.0f);

}

/*-----------------------------------------------------------------------------
Average two values
-----------------------------------------------------------------------------*/

float MathAverage (float n1, float n2)
{

  return (n1 + n2) / 2.0f;

}

/*-----------------------------------------------------------------------------
  This will take linear input values from 0.0 to 1.0 and convert them to 
  values along a curve.  This could also be acomplished with sin (), but this 
  way avoids converting to radians and back.
-----------------------------------------------------------------------------*/

float MathScalarCurve (float val)
{
 
  float   sign;

  val = (val - 0.5f) * 2.0f;
  if (val < 0.0f)
    sign = -1.0f;
  else 
    sign = 1.0f;
  if (val < 0.0f) 
    val = -val;
  val = 1.0f - val;
  val *= val;
  val = 1.0f - val;
  val *= sign;
  val = (val + 1.0f) / 2.0f;
  return val;

}

================================================
FILE: Math.h
================================================
float MathAngle (float angle);
float MathAngle (float x1, float y1, float x2, float y2);
float MathAngleDifference (float a1, float a2);
float MathAverage (float n1, float n2);
float MathInterpolate (float n1, float n2, float delta);
float MathLine_distance (float x1, float y1, float x2, float y2, float px, float py);
float MathDistance (float x1, float y1, float x2, float y2);
float MathDistance2 (float x1, float y1, float x2, float y2);
float MathSmoothStep (float val, float a, float b);
float MathScalarCurve (float val);

================================================
FILE: Mesh.cpp
================================================
/*-----------------------------------------------------------------------------

  Mesh.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This class is used to make constructing objects easier. It handles
  allocating vertex lists, polygon lists, and suchlike. 

  If you were going to implement vertex buffers, this would be the place to 
  do it.  Take away the _vertex member variable and store verts for ALL meshes
  in a common list, which could then be unloaded onto the good 'ol GPU.

-----------------------------------------------------------------------------*/

#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include <vector>
#include "glTypes.h"
#include "Mesh.h"

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CMesh::CMesh ()
{

  _list = glGenLists(1);
  _compiled = false;
  _polycount = 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CMesh::~CMesh ()
{

  glDeleteLists (_list, 1);
  _vertex.clear ();
  _fan.clear ();
  _quad_strip.clear ();
  _cube.clear ();


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CMesh::VertexAdd (const GLvertex& v)
{

  _vertex.push_back(v);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CMesh::CubeAdd (const cube& c)
{

  _cube.push_back(c);
  _polycount += 5;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CMesh::QuadStripAdd (const quad_strip& qs)
{

  _quad_strip.push_back(qs);
  _polycount += (qs.index_list.size() - 2) / 2;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CMesh::FanAdd (const fan& f)
{

  _fan.push_back(f);
  _polycount += f.index_list.size() - 2;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CMesh::Render ()
{

  std::vector<quad_strip>::iterator qsi;
  std::vector<cube>::iterator ci;
  std::vector<fan>::iterator fi;
  std::vector<int>::iterator n;

  if (_compiled) {
    glCallList (_list);
    return;
  }
  for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) {
    glBegin (GL_QUAD_STRIP);
    for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) {
      glTexCoord2fv (&_vertex[*n].uv.x);
      glVertex3fv (&_vertex[*n].position.x);
    }
    glEnd ();
  }
  for (ci = _cube.begin(); ci < _cube.end(); ++ci) {
    glBegin (GL_QUAD_STRIP);
    for (n = ci->index_list.begin(); n < ci->index_list.end(); ++n) {
      glTexCoord2fv (&_vertex[*n].uv.x);
      glVertex3fv (&_vertex[*n].position.x);
    }
    glEnd ();
    
    glBegin (GL_QUADS);
    glTexCoord2fv (&_vertex[ci->index_list[7]].uv.x);
    glVertex3fv (&_vertex[ci->index_list[7]].position.x);
    glVertex3fv (&_vertex[ci->index_list[5]].position.x);
    glVertex3fv (&_vertex[ci->index_list[3]].position.x);
    glVertex3fv (&_vertex[ci->index_list[1]].position.x);
    glEnd ();
    
    glBegin (GL_QUADS);
    glTexCoord2fv (&_vertex[ci->index_list[6]].uv.x);
    glVertex3fv (&_vertex[ci->index_list[0]].position.x);
    glVertex3fv (&_vertex[ci->index_list[2]].position.x);
    glVertex3fv (&_vertex[ci->index_list[4]].position.x);
    glVertex3fv (&_vertex[ci->index_list[6]].position.x);
    glEnd ();

  
  }
  for (fi = _fan.begin(); fi < _fan.end(); ++fi) {
    glBegin (GL_TRIANGLE_FAN);
    for (n = fi->index_list.begin(); n < fi->index_list.end(); ++n) {
      glTexCoord2fv (&_vertex[*n].uv.x);
      glVertex3fv (&_vertex[*n].position.x);
    }
    glEnd ();
  }

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CMesh::Compile ()
{

  glNewList (_list, GL_COMPILE);
  Render ();
  glEndList();	
  _compiled = true;

}


================================================
FILE: Mesh.h
================================================

#include <vector>

struct cube
{
  std::vector<int> index_list;   // probably always .size() == 10...
};

struct quad_strip
{
  std::vector<int> index_list;
};

struct fan
{
  std::vector<int> index_list;
};

class CMesh
{
public:
                          CMesh ();
                          ~CMesh ();
  unsigned                _list;
  int                     _polycount;
  std::vector<GLvertex>   _vertex;  
  std::vector<cube>       _cube;
  std::vector<quad_strip> _quad_strip;
  std::vector<fan>        _fan;
  bool                    _compiled;

  void        VertexAdd (const GLvertex& v);
  int         VertexCount () { return _vertex.size(); }
  int         PolyCount () { return _polycount; }
  void        CubeAdd (const cube& c);
  void        QuadStripAdd (const quad_strip& qs);
  void        FanAdd (const fan& f);
  void        Render ();
  void        Compile ();

};


================================================
FILE: PixelCity.dsp
================================================
# Microsoft Developer Studio Project File - Name="PixelCity" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Application" 0x0101

CFG=PixelCity - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "PixelCity.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "PixelCity.mak" CFG="PixelCity - Win32 Debug"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "PixelCity - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "PixelCity - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName "PixelCity"
# PROP Scc_LocalPath "."
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe

!IF  "$(CFG)" == "PixelCity - Win32 Release"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 /out:"Release/PixelCity.scr"

!ELSEIF  "$(CFG)" == "PixelCity - Win32 Debug"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /profile /debug /machine:I386

!ENDIF 

# Begin Target

# Name "PixelCity - Win32 Release"
# Name "PixelCity - Win32 Debug"
# Begin Group "Source Files"

# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Group "glTypes"

# PROP Default_Filter ""
# Begin Source File

SOURCE=.\glBbox.cpp
# End Source File
# Begin Source File

SOURCE=.\glMatrix.cpp
# End Source File
# Begin Source File

SOURCE=.\glQuat.cpp
# End Source File
# Begin Source File

SOURCE=.\glRgba.cpp
# End Source File
# Begin Source File

SOURCE=.\glVector2.cpp
# End Source File
# Begin Source File

SOURCE=.\glVector3.cpp
# End Source File
# End Group
# Begin Source File

SOURCE=.\Building.cpp
# End Source File
# Begin Source File

SOURCE=.\Camera.cpp
# End Source File
# Begin Source File

SOURCE=.\Car.cpp
# End Source File
# Begin Source File

SOURCE=.\Deco.cpp
# End Source File
# Begin Source File

SOURCE=.\Entity.cpp
# End Source File
# Begin Source File

SOURCE=.\Ini.cpp
# End Source File
# Begin Source File

SOURCE=.\Light.cpp
# End Source File
# Begin Source File

SOURCE=.\Math.cpp
# End Source File
# Begin Source File

SOURCE=.\Mesh.cpp
# End Source File
# Begin Source File

SOURCE=.\Random.cpp
# End Source File
# Begin Source File

SOURCE=.\Render.cpp
# End Source File
# Begin Source File

SOURCE=.\Sky.cpp
# End Source File
# Begin Source File

SOURCE=.\Texture.cpp
# End Source File
# Begin Source File

SOURCE=.\Visible.cpp
# End Source File
# Begin Source File

SOURCE=.\Win.cpp
# End Source File
# Begin Source File

SOURCE=.\World.cpp
# End Source File
# End Group
# Begin Group "Header Files"

# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File

SOURCE=.\Building.h
# End Source File
# Begin Source File

SOURCE=.\Camera.h
# End Source File
# Begin Source File

SOURCE=.\Car.h
# End Source File
# Begin Source File

SOURCE=.\Deco.h
# End Source File
# Begin Source File

SOURCE=.\Entity.h
# End Source File
# Begin Source File

SOURCE=.\glTypes.h
# End Source File
# Begin Source File

SOURCE=.\Ini.h
# End Source File
# Begin Source File

SOURCE=.\Light.h
# End Source File
# Begin Source File

SOURCE=.\Macro.h
# End Source File
# Begin Source File

SOURCE=.\Math.h
# End Source File
# Begin Source File

SOURCE=.\Mesh.h
# End Source File
# Begin Source File

SOURCE=.\Random.h
# End Source File
# Begin Source File

SOURCE=.\Render.h
# End Source File
# Begin Source File

SOURCE=.\Sky.h
# End Source File
# Begin Source File

SOURCE=.\Texture.h
# End Source File
# Begin Source File

SOURCE=.\Visible.h
# End Source File
# Begin Source File

SOURCE=.\Win.h
# End Source File
# Begin Source File

SOURCE=.\World.h
# End Source File
# End Group
# Begin Group "Resource Files"

# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project


================================================
FILE: Random.cpp
================================================
/*-----------------------------------------------------------------------------
									               r a n d o m
-----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
  The Mersenne Twister by Matsumoto and Nishimura <matumoto@math.keio.ac.jp>.
  It sets new standards for the period, quality and speed of random number
  generators. The incredible period is 2^19937 - 1, a number with about 6000
  digits; the 32-bit random numbers exhibit best possible equidistribution
  properties in dimensions up to 623; and it's fast, very fast. 
-----------------------------------------------------------------------------*/


#define LOWER_MASK            0x7fffffff 
#define M                     397
#define MATRIX_A              0x9908b0df 
#define N                     624
#define TEMPERING_MASK_B      0x9d2c5680
#define TEMPERING_MASK_C      0xefc60000
#define TEMPERING_SHIFT_L(y)  (y >> 18)
#define TEMPERING_SHIFT_S(y)  (y << 7)
#define TEMPERING_SHIFT_T(y)  (y << 15)
#define TEMPERING_SHIFT_U(y)  (y >> 11)
#define UPPER_MASK            0x80000000 

#include <memory.h>
#include "random.h"

static int              k = 1;
static unsigned long    mag01[2] = {0x0, MATRIX_A};
static unsigned long    ptgfsr[N];

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

unsigned long RandomVal (void)
{

  int		            kk;
  unsigned long	    y;
  
  if (k == N) {
    for (kk = 0; kk < N - M; kk++) {
      y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
      ptgfsr[kk] = ptgfsr[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
      }
    for (; kk < N - 1; kk++) {
      y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
      ptgfsr[kk] = ptgfsr[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
      }
    y = (ptgfsr[N - 1] & UPPER_MASK) | (ptgfsr[0] & LOWER_MASK);
    ptgfsr[N - 1] = ptgfsr[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
    k = 0;
    }
  y = ptgfsr[k++];
  y ^= TEMPERING_SHIFT_U (y);
  y ^= TEMPERING_SHIFT_S (y) & TEMPERING_MASK_B;
  y ^= TEMPERING_SHIFT_T (y) & TEMPERING_MASK_C;
  return y ^= TEMPERING_SHIFT_L (y);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

unsigned long RandomVal (int range)
{

  return range ? (RandomVal () % range) : 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RandomInit (unsigned long seed)
{

  //int	    k;
  
  //memset (ptgfsr, 0, sizeof (ptgfsr));
  //mag01[0] = 0x0;
  //mag01[1] = MATRIX_A;
  ptgfsr[0] = seed;
  for (k = 1; k < N; k++)
    ptgfsr[k] = 69069 * ptgfsr[k - 1];
  k = 1;

}



================================================
FILE: Random.h
================================================
#define COIN_FLIP     (RandomVal (2) == 0)

unsigned long RandomVal (int range);
unsigned long RandomVal (void);
void          RandomInit (unsigned long seed);


================================================
FILE: Render.cpp
================================================
/*-----------------------------------------------------------------------------

  Render.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------
  
  This is the core of the gl rendering functions.  This contains the main 
  rendering function RenderUpdate (), which initiates the various 
  other renders in the other modules. 

-----------------------------------------------------------------------------*/

#define RENDER_DISTANCE     1280
#define MAX_TEXT            256
#define YOUFAIL(message)    {WinPopup (message);return;}
#define HELP_SIZE           sizeof(help)
#define COLOR_CYCLE_TIME    10000 //milliseconds
#define COLOR_CYCLE         (COLOR_CYCLE_TIME / 4)
#define FONT_COUNT          (sizeof (fonts) / sizeof (struct glFont))
#define FONT_SIZE           (LOGO_PIXELS - LOGO_PIXELS / 8)
#define BLOOM_SCALING       0.07f

#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <stdarg.h>
#include <math.h>

#include <gl\gl.h>
#include <gl\glu.h>

#include "gltypes.h"
#include "entity.h"
#include "car.h"
#include "camera.h"
#include "ini.h"
#include "light.h"
#include "macro.h"
#include "math.h"
#include "render.h"
#include "sky.h"
#include "texture.h"
#include "world.h"
#include "win.h"

static	PIXELFORMATDESCRIPTOR pfd =			
{
	sizeof(PIXELFORMATDESCRIPTOR),			
	1,											  // Version Number
	PFD_DRAW_TO_WINDOW |			// Format Must Support Window
	PFD_SUPPORT_OPENGL |			// Format Must Support OpenGL
	PFD_DOUBLEBUFFER,					// Must Support Double Buffering
	PFD_TYPE_RGBA,						// Request An RGBA Format
	32,										    // Select Our glRgbaDepth
	0, 0, 0, 0, 0, 0,					// glRgbaBits Ignored
	0,											  // No Alpha Buffer
	0,											  // Shift Bit Ignored
	0,											  // Accumulation Buffers
	0, 0, 0, 0,								// Accumulation Bits Ignored
	16,											  // Z-Buffer (Depth Buffer)  bits
	0,											  // Stencil Buffers
	1,											  // Auxiliary Buffers
	PFD_MAIN_PLANE,						// Main Drawing Layer
	0,											  // Reserved
	0, 0, 0										// Layer Masks Ignored
};

static char             help[] = 
  "ESC - Exit!\n" 
  "F1  - Show this help screen\n" 
  "R   - Rebuild city\n" 
  "L   - Toggle 'letterbox' mode\n"
  "F   - Show Framecounter\n"
  "W   - Toggle Wireframe\n"
  "E   - Change full-scene effects\n"
  "T   - Toggle Textures\n"
  "G   - Toggle Fog\n"
;

struct glFont
{
  char*         name;
  unsigned		  base_char;
} fonts[] = 
{
  "Courier New",      0,
  "Arial",            0,
  "Times New Roman",  0,
  "Arial Black",      0,
  "Impact",           0,
  "Agency FB",        0,
  "Book Antiqua",     0,
};

#if SCREENSAVER
enum
{
  EFFECT_NONE,
  EFFECT_BLOOM,
  EFFECT_BLOOM_RADIAL,
  EFFECT_COLOR_CYCLE,
  EFFECT_GLASS_CITY,
  EFFECT_COUNT,
  EFFECT_DEBUG,
  EFFECT_DEBUG_OVERBLOOM,
};
#else
enum
{
  EFFECT_NONE,
  EFFECT_BLOOM,
  EFFECT_COUNT,
  EFFECT_DEBUG_OVERBLOOM,
  EFFECT_DEBUG,
  EFFECT_BLOOM_RADIAL,
  EFFECT_COLOR_CYCLE,
  EFFECT_GLASS_CITY,
};
#endif 

static HDC			        hDC;
static HGLRC		        hRC;
static float            render_aspect;
static float            fog_distance;
static int              render_width;
static int              render_height;
static bool             letterbox;
static int              letterbox_offset;
static int              effect;
static unsigned         next_fps;
static unsigned         current_fps;
static unsigned         frames;
static bool             show_wireframe;
static bool             flat;
static bool             show_fps;
static bool             show_fog;
static bool             show_help;

/*-----------------------------------------------------------------------------

  Draw a clock-ish progress.. widget... thing.  It's cute.

-----------------------------------------------------------------------------*/

static void do_progress (float center_x, float center_y, float radius, float opacity, float progress)
{

  int     i;
  int     end_angle;
  float   inner, outer;
  float   angle;
  float   s, c;
  float   gap;

  //Outer Ring
  gap = radius * 0.05f;
  outer = radius;
  inner = radius - gap * 2;
  glColor4f (1,1,1, opacity);
  glBegin (GL_QUAD_STRIP);
  for (i = 0; i <= 360; i+= 15) {
    angle = (float)i * DEGREES_TO_RADIANS;
    s = sinf (angle);
    c = -cosf (angle);
    glVertex2f (center_x + s * outer, center_y + c * outer);
    glVertex2f (center_x + s * inner, center_y + c * inner);
  }
  glEnd ();
  //Progress indicator
  glColor4f (1,1,1, opacity);
  end_angle = (int)(360 * progress);
  outer = radius - gap * 3;
  glBegin (GL_TRIANGLE_FAN);
  glVertex2f (center_x, center_y);
  for (i = 0; i <= end_angle; i+= 3) {
    angle = (float)i * DEGREES_TO_RADIANS;
    s = sinf (angle);
    c = -cosf (angle);
    glVertex2f (center_x + s * outer, center_y + c * outer);
  }
  glEnd ();
  //Tic lines
  glLineWidth (2.0f);
  outer = radius - gap * 1;
  inner = radius - gap * 2;
  glColor4f (0,0,0, opacity);
  glBegin (GL_LINES);
  for (i = 0; i <= 360; i+= 15) {
    angle = (float)i * DEGREES_TO_RADIANS;
    s = sinf (angle);
    c = -cosf (angle);
    glVertex2f (center_x + s * outer, center_y + c * outer);
    glVertex2f (center_x + s * inner, center_y + c * inner);
  }
  glEnd ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void do_effects (int type)
{

  float           hue1, hue2, hue3, hue4;
  GLrgba          color;
  float           fade;
  int             radius;
  int             x, y;
  int             i;
  int             bloom_radius;
  int             bloom_step;
  
  fade = WorldFade ();
  bloom_radius = 15;
  bloom_step = bloom_radius / 3;
  if (!TextureReady ())
    return;
  //Now change projection modes so we can render full-screen effects
  glMatrixMode (GL_PROJECTION);
  glPushMatrix ();
  glLoadIdentity ();
  glOrtho (0, render_width, render_height, 0, 0.1f, 2048);
	glMatrixMode (GL_MODELVIEW);
  glPushMatrix ();
  glLoadIdentity();
  glTranslatef(0, 0, -1.0f);				
  glDisable (GL_CULL_FACE);
  glDisable (GL_FOG);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  //Render full-screen effects
  glBlendFunc (GL_ONE, GL_ONE);
  glEnable (GL_TEXTURE_2D);
  glDisable(GL_DEPTH_TEST);
  glDepthMask (false);
  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_BLOOM));
  switch (type) {
  case EFFECT_DEBUG:
    glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_LOGOS));
    glDisable (GL_BLEND);
    glBegin (GL_QUADS);
    glColor3f (1, 1, 1);
    glTexCoord2f (0, 0);  glVertex2i (0, render_height / 4);
    glTexCoord2f (0, 1);  glVertex2i (0, 0);
    glTexCoord2f (1, 1);  glVertex2i (render_width / 4, 0);
    glTexCoord2f (1, 0);  glVertex2i (render_width / 4, render_height / 4);

    glTexCoord2f (0, 0);  glVertex2i (0, 512);
    glTexCoord2f (0, 1);  glVertex2i (0, 0);
    glTexCoord2f (1, 1);  glVertex2i (512, 0);
    glTexCoord2f (1, 0);  glVertex2i (512, 512);
    glEnd ();
    break;
  case EFFECT_BLOOM_RADIAL:
    //Psychedelic bloom
    glEnable (GL_BLEND);
    glBegin (GL_QUADS);
    color = WorldBloomColor () * BLOOM_SCALING * 2;
    glColor3fv (&color.red);
    for (i = 0; i <= 100; i+=10) {
      glTexCoord2f (0, 0);  glVertex2i (-i, i + render_height);
      glTexCoord2f (0, 1);  glVertex2i (-i, -i);
      glTexCoord2f (1, 1);  glVertex2i (i + render_width, -i);
      glTexCoord2f (1, 0);  glVertex2i (i + render_width, i + render_height);
    }
    glEnd ();
    break;
  case EFFECT_COLOR_CYCLE:
    //Oooh. Pretty colors.  Tint the scene according to screenspace.
    hue1 = (float)(GetTickCount () % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
    hue2 = (float)((GetTickCount () + COLOR_CYCLE) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
    hue3 = (float)((GetTickCount () + COLOR_CYCLE * 2) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
    hue4 = (float)((GetTickCount () + COLOR_CYCLE * 3) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;
    glBindTexture(GL_TEXTURE_2D, 0);
    glEnable (GL_BLEND);
    glBlendFunc (GL_ONE, GL_ONE);
    glBlendFunc (GL_DST_COLOR, GL_SRC_COLOR);
    glBegin (GL_QUADS);
    color = glRgbaFromHsl (hue1, 1.0f, 0.6f);
    glColor3fv (&color.red);
    glTexCoord2f (0, 0);  glVertex2i (0, render_height);
    color = glRgbaFromHsl (hue2, 1.0f, 0.6f);
    glColor3fv (&color.red);
    glTexCoord2f (0, 1);  glVertex2i (0, 0);
    color = glRgbaFromHsl (hue3, 1.0f, 0.6f);
    glColor3fv (&color.red);
    glTexCoord2f (1, 1);  glVertex2i (render_width, 0);
    color = glRgbaFromHsl (hue4, 1.0f, 0.6f);
    glColor3fv (&color.red);
    glTexCoord2f (1, 0);  glVertex2i (render_width, render_height);
    glEnd ();
    break;
  case EFFECT_BLOOM:
    //Simple bloom effect
    glBegin (GL_QUADS);
    color = WorldBloomColor () * BLOOM_SCALING;
    glColor3fv (&color.red);
    for (x = -bloom_radius; x <= bloom_radius; x += bloom_step) {
      for (y = -bloom_radius; y <= bloom_radius; y += bloom_step) {
        if (abs (x) == abs (y) && x)
          continue;
        glTexCoord2f (0, 0);  glVertex2i (x, y + render_height);
        glTexCoord2f (0, 1);  glVertex2i (x, y);
        glTexCoord2f (1, 1);  glVertex2i (x + render_width, y);
        glTexCoord2f (1, 0);  glVertex2i (x + render_width, y + render_height);
      }
    }
    glEnd ();
    break;
  case EFFECT_DEBUG_OVERBLOOM:
    //This will punish that uppity GPU. Good for testing low frame rate behavior.
    glBegin (GL_QUADS);
    color = WorldBloomColor () * 0.01f;
    glColor3fv (&color.red);
    for (x = -50; x <= 50; x+=5) {
      for (y = -50; y <= 50; y+=5) {
        glTexCoord2f (0, 0);  glVertex2i (x, y + render_height);
        glTexCoord2f (0, 1);  glVertex2i (x, y);
        glTexCoord2f (1, 1);  glVertex2i (x + render_width, y);
        glTexCoord2f (1, 0);  glVertex2i (x + render_width, y + render_height);
      }
    }
    glEnd ();
    break;
  }
  //Do the fade to / from darkness used to hide scene transitions
  if (LOADING_SCREEN) {
    if (fade > 0.0f) {
      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable (GL_BLEND);
      glDisable (GL_TEXTURE_2D);
      glColor4f (0, 0, 0, fade);
      glBegin (GL_QUADS);
      glVertex2i (0, 0);
      glVertex2i (0, render_height);
      glVertex2i (render_width, render_height);
      glVertex2i (render_width, 0);
      glEnd ();
    }
    if (TextureReady () && !EntityReady () && fade != 0.0f) {
      radius = render_width / 16;
      do_progress ((float)render_width / 2, (float)render_height / 2, (float)radius, fade, EntityProgress ());
      RenderPrint (render_width / 2 - LOGO_PIXELS, render_height / 2 + LOGO_PIXELS, 0, glRgba (0.5f), "%1.2f%%", EntityProgress () * 100.0f);
      RenderPrint (1, "%s v%d.%d.%03d", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
    }
  }
  glPopMatrix ();
  glMatrixMode (GL_PROJECTION);
  glPopMatrix ();
  glMatrixMode (GL_MODELVIEW);
  glEnable(GL_DEPTH_TEST);

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int RenderMaxTextureSize ()
{

  int mts;

  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mts);
  mts = MIN (mts, render_width);
  return MIN (mts, render_height);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderPrint (int x, int y, int font, GLrgba color, const char *fmt, ...)				
{

  char		  text[MAX_TEXT];	
  va_list		ap;					
  
  text[0] = 0;
  if (fmt == NULL)			
		  return;						
  va_start(ap, fmt);		
  vsprintf(text, fmt, ap);				
  va_end(ap);		
  glPushAttrib(GL_LIST_BIT);				
  glListBase(fonts[font % FONT_COUNT].base_char - 32);				
  glColor3fv (&color.red);
	glRasterPos2i (x, y);
  glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderPrint (int line, const char *fmt, ...)				
{

  char		  text[MAX_TEXT];	
	va_list		ap;			
	
  text[0] = 0;	
  if (fmt == NULL)			
		  return;						
  va_start (ap, fmt);		
  vsprintf (text, fmt, ap);				
  va_end (ap);		
  glMatrixMode (GL_PROJECTION);
  glPushMatrix ();
  glLoadIdentity ();
  glOrtho (0, render_width, render_height, 0, 0.1f, 2048);
  glDisable(GL_DEPTH_TEST);
  glDepthMask (false);
	glMatrixMode (GL_MODELVIEW);
  glPushMatrix ();
  glLoadIdentity();
  glTranslatef(0, 0, -1.0f);				
  glDisable (GL_BLEND);
  glDisable (GL_FOG);
  glDisable (GL_TEXTURE_2D);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  RenderPrint (0, line * FONT_SIZE - 2, 0, glRgba (0.0f), text);
  RenderPrint (4, line * FONT_SIZE + 2, 0, glRgba (0.0f), text);
  RenderPrint (2, line * FONT_SIZE, 0, glRgba (1.0f), text);
  glPopAttrib();						
  glPopMatrix ();
  glMatrixMode (GL_PROJECTION);
  glPopMatrix ();
  glMatrixMode (GL_MODELVIEW);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void static do_help (void)
{

  char*     text;
  int       line;
  char      parse[HELP_SIZE];
  int       x;
  
  strcpy (parse, help);
  line = 0;
  text = strtok (parse, "\n");
  x = 10;
  while (text) {
    RenderPrint (line + 2, text);
    text = strtok (NULL, "\n");
    line++;
  }

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void do_fps ()
{

  LIMIT_INTERVAL (1000);
  current_fps = frames;
  frames = 0;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderResize (void)		
{

  float     fovy;

  render_width = WinWidth ();
  render_height = WinHeight ();
  if (letterbox) {
    letterbox_offset = render_height / 6;
    render_height = render_height - letterbox_offset * 2;
  } else 
    letterbox_offset = 0;
  //render_aspect = (float)render_height / (float)render_width;
  glViewport (0, letterbox_offset, render_width, render_height);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  render_aspect = (float)render_width / (float)render_height;
  fovy = 60.0f;
  if (render_aspect > 1.0f) 
    fovy /= render_aspect; 
  gluPerspective (fovy, render_aspect, 0.1f, RENDER_DISTANCE);
	glMatrixMode (GL_MODELVIEW);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderTerm (void)
{

  if (!hRC)
    return;
  wglDeleteContext (hRC);
  hRC = NULL;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderInit (void)
{

  HWND              hWnd;
	unsigned		      PixelFormat;
  HFONT	            font;		
	HFONT	            oldfont;

  hWnd = WinHwnd ();
  if (!(hDC = GetDC (hWnd))) 
		YOUFAIL ("Can't Create A GL Device Context.") ;
	if (!(PixelFormat = ChoosePixelFormat(hDC,&pfd)))
		YOUFAIL ("Can't Find A Suitable PixelFormat.") ;
  if(!SetPixelFormat(hDC,PixelFormat,&pfd))
		YOUFAIL ("Can't Set The PixelFormat.");
	if (!(hRC = wglCreateContext (hDC)))	
		YOUFAIL ("Can't Create A GL Rendering Context.");
  if(!wglMakeCurrent(hDC,hRC))	
		YOUFAIL ("Can't Activate The GL Rendering Context.");
  //Load the fonts for printing debug info to the window.
  for (int i = 0; i < FONT_COUNT; i++) {
	  fonts[i].base_char = glGenLists(96); 
	  font = CreateFont (FONT_SIZE,	0, 0,	0,	
				  FW_BOLD, FALSE,	FALSE, FALSE,	DEFAULT_CHARSET,	OUT_TT_PRECIS,		
				  CLIP_DEFAULT_PRECIS,	ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH,
				  fonts[i].name);
	  oldfont = (HFONT)SelectObject(hDC, font);	
	  wglUseFontBitmaps(hDC, 32, 96, fonts[i].base_char);
	  SelectObject(hDC, oldfont);
	  DeleteObject(font);		
  }
  //If the program is running for the first time, set the defaults.
  if (!IniInt ("SetDefaults")) {
    IniIntSet ("SetDefaults", 1);
    IniIntSet ("Effect", EFFECT_BLOOM);
    IniIntSet ("ShowFog", 1);
  }
  //load in our settings
  letterbox = IniInt ("Letterbox") != 0;
  show_wireframe = IniInt ("Wireframe") != 0;
  show_fps = IniInt ("ShowFPS") != 0;
  show_fog = IniInt ("ShowFog") != 0;
  effect = IniInt ("Effect");
  flat = IniInt ("Flat") != 0;
  fog_distance = WORLD_HALF;
  //clear the viewport so the user isn't looking at trash while the program starts
  glViewport (0, 0, WinWidth (), WinHeight ());
  glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  SwapBuffers (hDC);
  RenderResize ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderFPSToggle ()
{

  show_fps = !show_fps;
  IniIntSet ("ShowFPS", show_fps ? 1 : 0);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool RenderFog ()
{

  return show_fog;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderFogToggle ()
{

  show_fog = !show_fog;
  IniIntSet ("ShowFog", show_fog ? 1 : 0);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderLetterboxToggle ()
{

  letterbox = !letterbox;
  IniIntSet ("Letterbox", letterbox ? 1 : 0);
  RenderResize ();


}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderWireframeToggle ()
{

  show_wireframe = !show_wireframe;
  IniIntSet ("Wireframe", show_wireframe ? 1 : 0);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool RenderWireframe ()
{

  return show_wireframe;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderEffectCycle ()
{

  effect = (effect + 1) % EFFECT_COUNT;
  IniIntSet ("Effect", effect);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool RenderBloom ()
{

  return effect == EFFECT_BLOOM || effect == EFFECT_BLOOM_RADIAL 
    || effect == EFFECT_DEBUG_OVERBLOOM || effect == EFFECT_COLOR_CYCLE;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool RenderFlat ()
{

  return flat;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderFlatToggle ()
{

  flat = !flat;
  IniIntSet ("Flat", flat ? 1 : 0);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderHelpToggle ()
{

  show_help = !show_help;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

float RenderFogDistance ()
{

  return fog_distance;

}

/*-----------------------------------------------------------------------------

  This is used to set a gradient fog that goes from camera to some portion of 
  the normal fog distance.  This is used for making wireframe outlines and
  flat surfaces fade out after rebuild.  Looks cool.

-----------------------------------------------------------------------------*/

void RenderFogFX (float scalar)
{

  if (scalar >= 1.0f) {
    glDisable (GL_FOG);
    return;
  }
  glFogf (GL_FOG_START, 0.0f);
  glFogf (GL_FOG_END, fog_distance * 2.0f * scalar);
  glEnable (GL_FOG);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void RenderUpdate (void)		
{

  GLvector        pos;
  GLvector        angle;
  GLrgba          color;
  int             elapsed;

  frames++;
  do_fps ();
  glViewport (0, 0, WinWidth (), WinHeight ());
  glDepthMask (true);
  glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
  glEnable(GL_DEPTH_TEST);
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  if (letterbox) 
    glViewport (0, letterbox_offset, render_width, render_height);
  if (LOADING_SCREEN && TextureReady () && !EntityReady ()) {
    do_effects (EFFECT_NONE);
    SwapBuffers (hDC);
    return;
  }
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glShadeModel(GL_SMOOTH);
  glFogi (GL_FOG_MODE, GL_LINEAR);
	glDepthFunc(GL_LEQUAL);
  glEnable (GL_CULL_FACE);
  glCullFace (GL_BACK);
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glMatrixMode (GL_TEXTURE);
  glLoadIdentity();
	glMatrixMode (GL_MODELVIEW);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glLoadIdentity();
  glLineWidth (1.0f);
  pos = CameraPosition ();
  angle = CameraAngle ();
  glRotatef (angle.x, 1.0f, 0.0f, 0.0f);
  glRotatef (angle.y, 0.0f, 1.0f, 0.0f);
  glRotatef (angle.z, 0.0f, 0.0f, 1.0f);
  glTranslatef (-pos.x, -pos.y, -pos.z);
  glEnable (GL_TEXTURE_2D);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  //Render all the stuff in the whole entire world.
  glDisable (GL_FOG);
  SkyRender ();
  if (show_fog) {
    glEnable (GL_FOG);
    glFogf (GL_FOG_START, fog_distance - 100);
    glFogf (GL_FOG_END, fog_distance);
    color = glRgba (0.0f);
    glFogfv (GL_FOG_COLOR, &color.red);
  }
  WorldRender ();
  if (effect == EFFECT_GLASS_CITY) {
    glDisable (GL_CULL_FACE);
    glEnable (GL_BLEND);
    glBlendFunc (GL_ONE, GL_ONE);
    glDepthFunc (false);
    glDisable(GL_DEPTH_TEST);
    glMatrixMode (GL_TEXTURE);
    glTranslatef ((pos.x + pos.z) / SEGMENTS_PER_TEXTURE, 0, 0);
	  glMatrixMode (GL_MODELVIEW);
  } else {
    glEnable (GL_CULL_FACE);
    glDisable (GL_BLEND);
  }
  EntityRender ();
  if (!LOADING_SCREEN) {
    elapsed = 3000 - WorldSceneElapsed ();
    if (elapsed >= 0 && elapsed <= 3000) {
      RenderFogFX ((float)elapsed / 3000.0f);
      glDisable (GL_TEXTURE_2D);
      glEnable (GL_BLEND);
      glBlendFunc (GL_ONE, GL_ONE);
      EntityRender ();
    }
  } 
  if (EntityReady ())
    LightRender ();
  CarRender ();
  if (show_wireframe) {
    glDisable (GL_TEXTURE_2D);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    EntityRender ();
  }
  do_effects (effect);
  //Framerate tracker
  if (show_fps) 
    RenderPrint (1, "FPS=%d : Entities=%d : polys=%d", current_fps, EntityCount () + LightCount () + CarCount (), EntityPolyCount () + LightCount () + CarCount ());
  //Show the help overlay
  if (show_help)
    do_help ();
  SwapBuffers (hDC);

}


================================================
FILE: Render.h
================================================
bool  RenderBloom ();
void  RenderEffectCycle ();
bool  RenderFlat ();
void  RenderFlatToggle ();
float RenderFogDistance ();
bool  RenderFog ();
void  RenderFogToggle ();
void  RenderFogFX (float scalar);
void  RenderFPSToggle ();
void  RenderInit ();
void  RenderLetterboxToggle ();
int   RenderMaxTextureSize ();
void  RenderResize ();
void  RenderTerm ();
void  RenderUpdate ();
bool  RenderWireframe ();
void  RenderWireframeToggle ();
void  RenderHelpToggle ();
void  RenderPrint (int x, int y, int font, GLrgba color, const char *fmt, ...);
void  RenderPrint (int line, const char *fmt, ...);









================================================
FILE: Sky.cpp
================================================
/*-----------------------------------------------------------------------------

  Sky.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  Did this need to be written as a class? It did not. There will never be 
  more than one sky in play, so the whole class structure here is superflous,
  but harmless.
  
-----------------------------------------------------------------------------*/

#define SKYPOINTS      24

#include <windows.h>
#include <math.h>
#include <gl\gl.h>

#include "camera.h"
#include "macro.h"
#include "math.h"
#include "random.h"
#include "render.h"
#include "sky.h"
#include "texture.h"
#include "glTypes.h"
#include "world.h"

static CSky*          sky;

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void SkyRender ()
{

  if (sky && !RenderFlat ())
    sky->Render ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void SkyClear ()
{

  if(sky)
    delete sky;
  sky = NULL;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CSky::Render ()
{

  GLvector    angle, position;

  if (!TextureReady ())
    return;
  glDepthMask (false);
  glPushAttrib (GL_POLYGON_BIT | GL_FOG_BIT);
  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  glDisable (GL_CULL_FACE);
  glDisable (GL_FOG);
  glPushMatrix ();
  glLoadIdentity();
  angle = CameraAngle ();
  position = CameraPosition ();
  glRotatef (angle.x, 1.0f, 0.0f, 0.0f);
  glRotatef (angle.y, 0.0f, 1.0f, 0.0f);
  glRotatef (angle.z, 0.0f, 0.0f, 1.0f);
  glTranslatef (0.0f, -position.y / 100.0f, 0.0f);
  glEnable (GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_SKY));
  glCallList (m_list);
  glPopMatrix ();
  glPopAttrib ();
  glDepthMask (true);
  glEnable (GL_COLOR_MATERIAL);


}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

CSky::CSky ()
{

  GLvertex      circle[SKYPOINTS];
  GLvector      pos;
  float         angle;
  int           i;
  float         size;
  float         rad;
  float         lum;

  size = 10.0f;
  for (i = 0; i < SKYPOINTS; i++) {
    angle = (float)i / (float)(SKYPOINTS - 1);
    angle *= 360;
    angle *= DEGREES_TO_RADIANS;
    circle[i].position.x = sinf (angle) * size;
    circle[i].position.y = 0.1f;
    circle[i].position.z = cosf (angle) * size;
    circle[i].uv.x = ((float)i / (float)(SKYPOINTS - 1)) * 5.0f;
    circle[i].uv.y = 0.5f;
    rad = ((float)i / (SKYPOINTS - 1)) * 180.0f * DEGREES_TO_RADIANS;
    lum = sinf (rad);
    lum = (float)pow (lum, 5);
    circle[i].color = glRgba (lum);
  }
  m_list = glGenLists(1);
  glNewList (m_list, GL_COMPILE);
  glColor3f (1, 1, 1);
  
  glBegin (GL_QUAD_STRIP);
  for (i = 0; i < SKYPOINTS; i++) {
    glTexCoord2f (circle[i].uv.x, 0.0f);
    glVertex3fv (&circle[i].position.x);
    pos = circle[i].position;
    pos.y = size / 3.5f;
    glTexCoord2f (circle[i].uv.x, 1.0f);
    glVertex3fv (&pos.x);
  }
  glEnd ();
  glEndList();	
  sky = this;

}

================================================
FILE: Sky.h
================================================
#define SKY_GRID      21
#define SKY_HALF      (SKY_GRID / 2)

struct sky_point
{
  GLrgba        color;
  GLvector      position;
};

class CSky 
{
private:
  int                     m_list;
  int                     m_stars_list;
  sky_point               m_grid[SKY_GRID][SKY_GRID];

public:
                          CSky ();
  void                    Render (void);

};

void SkyRender ();
void SkyClear ();


================================================
FILE: Texture.cpp
================================================
/*-----------------------------------------------------------------------------

  Texture.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------
  
  This procedurally builds all of the textures.  

  I apologize in advance for the apalling state of this module. It's the victim 
  of iterative and experimental development.  It has cruft, poorly named
  functions, obscure code, poorly named variables, and is badly organized. Even
  the formatting sucks in places. Its only saving grace is that it works.
  
-----------------------------------------------------------------------------*/

#define RANDOM_COLOR_SHIFT  ((float)(RandomVal (10)) / 50.0f)
#define RANDOM_COLOR_VAL    ((float)(RandomVal (256)) / 256.0f)
#define RANDOM_COLOR_LIGHT  ((float)(200 + RandomVal (56)) / 256.0f)
#define SKY_BANDS           (sizeof (sky_pos) / sizeof (int))
#define PREFIX_COUNT        (sizeof (prefix) / sizeof (char*))
#define SUFFIX_COUNT        (sizeof (suffix) / sizeof (char*))
#define NAME_COUNT          (sizeof (name) / sizeof (char*))

#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>

#include "gltypes.h"
#include "building.h"
#include "camera.h"
#include "car.h"
#include "light.h"
#include "macro.h"
#include "random.h"
#include "render.h"
#include "sky.h"
#include "texture.h"
#include "world.h"
#include "win.h"

static char*        prefix[] = 
{
  "i", 
  "Green ",
  "Mega",
  "Super ",
  "Omni",
  "e",
  "Hyper",
  "Global ",
  "Vital", 
  "Next ",
  "Pacific ",
  "Metro",
  "Unity ",
  "G-",
  "Trans",
  "Infinity ", 
  "Superior ",
  "Monolith ",
  "Best ",
  "Atlantic ",
  "First ",
  "Union ",
  "National ",
};

static char*        name[] = 
{
  "Biotic",
  "Info",
  "Data",
  "Solar",
  "Aerospace",
  "Motors",
  "Nano",
  "Online",
  "Circuits",
  "Energy",
  "Med",
  "Robotic",
  "Exports",
  "Security",
  "Systems",
  "Financial",
  "Industrial",
  "Media",
  "Materials",
  "Foods",
  "Networks",
  "Shipping",
  "Tools",
  "Medical",
  "Publishing",
  "Enterprises",
  "Audio",
  "Health",
  "Bank",
  "Imports",
  "Apparel",
  "Petroleum", 
  "Studios",
};

static char*        suffix[] = 
{
  "Corp",
  " Inc.",
  "Co",
  "World",
  ".Com",
  " USA",
  " Ltd.",
  "Net",
  " Tech",
  " Labs",
  " Mfg.",
  " UK",
  " Unlimited",
  " One",
  " LLC"
};
  
class CTexture
{
public:
  int               _my_id;
  unsigned          _glid;
  int               _desired_size;
  int               _size;
  int               _half;
  int               _segment_size;
  bool              _ready;
  bool              _masked;
  bool              _mipmap;
  bool              _clamp;
public:
  CTexture*         _next;
                    CTexture (int id, int size, bool mipmap, bool clamp, bool masked);
  void              Clear () { _ready = false; }
  void              Rebuild ();
  void              DrawWindows ();
  void              DrawSky ();
  void              DrawHeadlight ();
};

static CTexture*    head;
static bool         textures_done;
static bool         prefix_used[PREFIX_COUNT];
static bool         name_used[NAME_COUNT];
static bool         suffix_used[SUFFIX_COUNT];
static int          build_time;

/*-----------------------------------------------------------------------------
                          
-----------------------------------------------------------------------------*/

void drawrect_simple (int left, int top, int right, int bottom, GLrgba color)
{

  glColor3fv (&color.red);
  glBegin (GL_QUADS);
  glVertex2i (left, top);
  glVertex2i (right, top);
  glVertex2i (right, bottom);
  glVertex2i (left, bottom);
  glEnd ();

}


/*-----------------------------------------------------------------------------
                          
-----------------------------------------------------------------------------*/

void drawrect_simple (int left, int top, int right, int bottom, GLrgba color1, GLrgba color2)
{

  glColor3fv (&color1.red);
  glBegin (GL_TRIANGLE_FAN);
  glVertex2i ((left + right) / 2, (top + bottom) / 2);
  glColor3fv (&color2.red);
  glVertex2i (left, top);
  glVertex2i (right, top);
  glVertex2i (right, bottom);
  glVertex2i (left, bottom);
  glVertex2i (left, top);
  glEnd ();

}


/*-----------------------------------------------------------------------------
                          
-----------------------------------------------------------------------------*/

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 ();
      }
    }
  }
}

/*-----------------------------------------------------------------------------
                          
-----------------------------------------------------------------------------*/

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;
  }

}

/*-----------------------------------------------------------------------------
                          
-----------------------------------------------------------------------------*/

static void do_bloom (CTexture* t)
{

  glBindTexture(GL_TEXTURE_2D, 0);		
  glViewport(0, 0, t->_size , t->_size);
  glCullFace (GL_BACK);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDepthMask (true);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glEnable(GL_DEPTH_TEST);
  glEnable (GL_CULL_FACE);
  glCullFace (GL_BACK);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable (GL_FOG);
  glFogf (GL_FOG_START, RenderFogDistance () / 2);
  glFogf (GL_FOG_END, RenderFogDistance ());
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable (GL_TEXTURE_2D);
  EntityRender ();
  CarRender ();
  LightRender ();
  glBindTexture(GL_TEXTURE_2D, t->_glid);		
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, t->_size, t->_size, 0);

}

/*-----------------------------------------------------------------------------
                          
-----------------------------------------------------------------------------*/

CTexture::CTexture (int id, int size, bool mipmap, bool clamp, bool masked)
{

  glGenTextures (1, &_glid); 
  _my_id = id;
  _mipmap = mipmap;
  _clamp = clamp;
  _masked = masked;
  _desired_size = size;
  _size = size;
  _half = size / 2;
  _segment_size = size / SEGMENTS_PER_TEXTURE;
  _ready = false;
  _next = head;
  head = this;

}

/*-----------------------------------------------------------------------------

  This draws all of the windows on a building texture. lit_density controls 
  how many lights are on. (1 in n chance that the light is on. Higher values 
  mean less lit windows. run_length controls how often it will consider 
  changing the lit / unlit status. 1 produces a complete scatter, higher
  numbers make long strings of lights.
  
-----------------------------------------------------------------------------*/

void CTexture::DrawWindows ()
{


  int         x, y;
  int         run;
  int         run_length;
  int         lit_density;
  GLrgba      color;
  bool        lit;

  //color = glRgbaUnique (_my_id);
  for (y = 0; y < SEGMENTS_PER_TEXTURE; y++)  {
    //Every few floors we change the behavior
    if (!(y % 8)) {
      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--;

    }
  }

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

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 ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void CTexture::DrawHeadlight ()
{

  float           radius;
  int             i, x, y;
  GLvector2       pos;

  //Make a simple circle of light, bright in the center and fading out
  radius = ((float)_half) - 20;
  x = _half - 20;
  y = _half;
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glBegin (GL_TRIANGLE_FAN);
  glColor4f (0.8f, 0.8f, 0.8f, 0.6f);
  glVertex2i (_half - 5, y);
  glColor4f (0, 0, 0, 0);
  for (i = 0; i <= 360; i += 36) {
    pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
    pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
    glVertex2i (x + (int)pos.x, _half + (int)pos.y);
  }
  glEnd ();
  x = _half + 20;
  glBegin (GL_TRIANGLE_FAN);
  glColor4f (0.8f, 0.8f, 0.8f, 0.6f);
  glVertex2i (_half + 5, y);
  glColor4f (0, 0, 0, 0);
  for (i = 0; i <= 360; i += 36) {
    pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
    pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;
    glVertex2i (x + (int)pos.x, _half + (int)pos.y);
  }
  glEnd ();
  x = _half - 6;
  drawrect_simple (x - 3, y - 2, x + 2, y + 2, glRgba (1.0f));
  x = _half + 6;
  drawrect_simple (x - 2, y - 2, x + 3, y + 2, glRgba (1.0f));

}

/*-----------------------------------------------------------------------------

  Here is where ALL of the procedural textures are created.  It's filled with 
  obscure logic, magic numbers, and messy code. Part of this is because 
  there is a lot of "art" being done here, and lots of numbers that could be 
  endlessly tweaked.  Also because I'm lazy.
                    
-----------------------------------------------------------------------------*/

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;
    

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

unsigned TextureId (int id)
{

  for (CTexture* t = head; t; t = t->_next) {
    if (t->_my_id == id)
      return t->_glid;
  }
  return 0;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

unsigned TextureRandomBuilding (int index)
{

  index = abs (index) % BUILDING_COUNT;
  return TextureId (TEXTURE_BUILDING1 + index);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void TextureReset (void)
{

  textures_done = false;
  build_time = 0;
  for (CTexture* t = head; t; t = t->_next)
    t->Clear ();
  ZeroMemory (prefix_used, sizeof (prefix_used));
  ZeroMemory (name_used, sizeof (name_used));
  ZeroMemory (suffix_used, sizeof (suffix_used));

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool TextureReady ()
{

  return textures_done;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void TextureUpdate (void)
{

  if (textures_done) {
    if (!RenderBloom ())
      return;
    CTexture*   t;

    for (t = head; t; t = t->_next) {
      if (t->_my_id != TEXTURE_BLOOM) 
        continue;
      do_bloom (t);
      return;
    }
  }
  for (CTexture* t = head; t; t = t->_next) {
    if (!t->_ready) {
      t->Rebuild();
      return;
    }
  } 
  textures_done = true;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void TextureTerm (void)
{

  CTexture*    t;

  while (head) {
    t = head->_next;
    free (head);
    head = t;
  }

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void TextureInit (void)
{

  new CTexture (TEXTURE_SKY,          512,  true,  false, false);
  new CTexture (TEXTURE_LATTICE,      128,  true,  true,  true);
  new CTexture (TEXTURE_LIGHT,        128,  false, false, true);
  new CTexture (TEXTURE_SOFT_CIRCLE,  128,  false, false, true);
  new CTexture (TEXTURE_HEADLIGHT,    128,  false, false, true);
  new CTexture (TEXTURE_TRIM,  TRIM_RESOLUTION,  true, false, false);
  new CTexture (TEXTURE_LOGOS, LOGO_RESOLUTION,  true, false, true);
  for (int i = TEXTURE_BUILDING1; i <= TEXTURE_BUILDING9; i++)
    new CTexture (i, 512, true, false, false);
  new CTexture (TEXTURE_BLOOM,  512,  true, false, false);
  int  names = PREFIX_COUNT * NAME_COUNT + SUFFIX_COUNT * NAME_COUNT;

}


================================================
FILE: Texture.h
================================================
#define SEGMENTS_PER_TEXTURE  64
#define ONE_SEGMENT           (1.0f / SEGMENTS_PER_TEXTURE)
#define LANES_PER_TEXTURE     8
#define LANE_SIZE             (1.0f / LANES_PER_TEXTURE)
#define LANE_PIXELS           (_size / LANES_PER_TEXTURE)
#define TRIM_RESOLUTION       256
#define TRIM_ROWS             4
#define TRIM_SIZE             (1.0f / TRIM_ROWS)
#define TRIM_PIXELS           (TRIM_RESOLUTION / TRIM_ROWS)
#define LOGO_RESOLUTION       512
#define LOGO_ROWS             16
#define LOGO_SIZE             (1.0f / LOGO_ROWS)
#define LOGO_PIXELS           (LOGO_RESOLUTION / LOGO_ROWS)

enum
{
  TEXTURE_LIGHT,
  TEXTURE_SOFT_CIRCLE,
  TEXTURE_SKY,
  TEXTURE_LOGOS,
  TEXTURE_TRIM,
  TEXTURE_BLOOM,
  TEXTURE_HEADLIGHT,
  TEXTURE_LATTICE,
  TEXTURE_BUILDING1,
  TEXTURE_BUILDING2,
  TEXTURE_BUILDING3,
  TEXTURE_BUILDING4,
  TEXTURE_BUILDING5,
  TEXTURE_BUILDING6,
  TEXTURE_BUILDING7,
  TEXTURE_BUILDING8,
  TEXTURE_BUILDING9,
  TEXTURE_COUNT,
};

#define BUILDING_COUNT    ((TEXTURE_BUILDING9 - TEXTURE_BUILDING1) + 1)

unsigned  TextureFromName (char* name);
unsigned  TextureId (int id);
void      TextureInit (void);
void      TextureTerm (void);
unsigned  TextureRandomBuilding (int index);
bool      TextureReady ();
void      TextureReset (void);
void      TextureUpdate (void);



================================================
FILE: Visible.cpp
================================================
/*-----------------------------------------------------------------------------

  Visible.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This module runs the visibility grid, a 2-dimensional array that aids in
  culling objects during rendering. 

  There are many ways this could be refined or sped up, although tests indicate
  it's not a huge drain on performance.

-----------------------------------------------------------------------------*/


#include <windows.h>
#include <math.h>

#include "glTypes.h"
#include "camera.h"
#include "macro.h"
#include "math.h"
#include "visible.h"
#include "world.h"
#include "win.h"

static bool          vis_grid[GRID_SIZE][GRID_SIZE];

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool Visible (GLvector pos)
{

  return vis_grid[WORLD_TO_GRID(pos.x)][WORLD_TO_GRID(pos.z)];

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool Visible (int x, int z)
{

  return vis_grid[x][z];

}



/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void VisibleUpdate (void)
{

  GLvector  angle;
  GLvector  position;
  int       x, y, grid_x, grid_z;
  int       left, right, front, back;
  float     angle_to;
  float     angle_diff;
  float     target_x, target_z;

  //Clear the visibility table
  ZeroMemory (vis_grid, sizeof (vis_grid));
  //Calculate which cell the camera is in
  angle = CameraAngle ();
  position = CameraPosition ();
  grid_x = WORLD_TO_GRID(position.x);
  grid_z = WORLD_TO_GRID(position.z);
  //Cells directly adjactent to the camera might technically fall out of the fov,
  //but still have a few objects poking into screenspace when looking up or down.
  //Rather than obsess over sorting those objects properly, it's more efficient to
  //just mark them visible.
  left = right = front = back = 3;
  //Looking north, can't see south.
  if (angle.y < 45.0f || angle.y > 315.0f)
    front = 0;
  //Looking south, can't see north
  if (angle.y > 135.0f && angle.y < 225.0f)
    back = 0;
  //Looking east, can't see west
  if (angle.y > 45.0f && angle.y < 135.0f)
    left = 0;
  //Looking west, can't see east
  if (angle.y > 225.0f && angle.y < 315.0f)
    right = 0;
  //Now mark the block around us the might be visible
  for (x = grid_x - left; x <= grid_x + right; x++) {
    if (x < 0 || x >= GRID_SIZE) //just in case the camera leaves the world map
      continue;
    for (y = grid_z - back; y <= grid_z + front; y++) {
      if (y < 0 || y >= GRID_SIZE) //just in case the camera leaves the world map
        continue;
      vis_grid[x][y] = true;
    }
  }
  //Doesn't matter where we are facing, objects in current cell are always visible
  vis_grid[grid_x][grid_z] = true;
  //Here, we look at the angle from the current camera position to the cell 
  //on the grid, and how much that angle deviates from the current view angle. 
  for (x = 0; x < GRID_SIZE; x++) {
    for (y = 0; y < GRID_SIZE; y++) {
      //if we marked it visible earlier, skip all this math
      if (vis_grid[x][y])
        continue;
      //if the camera is to the left of this cell, use the left edge
      if (grid_x < x) 
        target_x = (float)x * GRID_RESOLUTION;
      else 
        target_x = (float)(x + 1) * GRID_RESOLUTION;
      if (grid_z < y) 
        target_z = (float)y * GRID_RESOLUTION;
      else
        target_z = (float)(y + 1) * GRID_RESOLUTION;
      angle_to = 180 - MathAngle (target_x, target_z, position.x, position.z);
      //Store how many degrees the cell is to the 
      angle_diff = (float)fabs (MathAngleDifference (angle.y, angle_to));
      vis_grid[x][y] = angle_diff < 45;
    }
  }


}
  


================================================
FILE: Visible.h
================================================
#define GRID_RESOLUTION   32
#define GRID_CELL         (GRID_RESOLUTION / 2)
#define GRID_SIZE         (WORLD_SIZE / GRID_RESOLUTION)
#define WORLD_TO_GRID(x)  (int)(x / GRID_RESOLUTION)
#define GRID_TO_WORLD(x)  ((float)x * GRID_RESOLUTION)



void VisibleUpdate (void);
bool Visible (GLvector pos);
bool Visible (int x, int z);


================================================
FILE: Win.cpp
================================================
/*-----------------------------------------------------------------------------

  Win.cpp

  2006 Shamus Young

-------------------------------------------------------------------------------

  Create the main window and make it go.

-----------------------------------------------------------------------------*/

#define MOUSE_MOVEMENT          0.5f

#include <windows.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <scrnsave.h>

#include "camera.h"
#include "car.h"
#include "entity.h"
#include "glTypes.h"
#include "ini.h"
#include "macro.h"
#include "random.h"
#include "render.h"
#include "texture.h"
#include "win.h"
#include "world.h"
#include "visible.h"

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "winmm.lib")
#pragma comment (lib, "glu32.lib")
#if SCREENSAVER
#pragma comment (lib, "scrnsave.lib")
#endif	



static HWND         hwnd;
static HINSTANCE    module;
static int          width;
static int          height;
static int          half_width;
static int          half_height;
static bool         lmb;
static bool         rmb;
static bool         mouse_forced;
static POINT        select_pos;
static POINT        mouse_pos;
static bool         quit;
static HINSTANCE    instance;

LONG WINAPI ScreenSaverProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void CenterCursor ()
{

  int             center_x;
  int             center_y;
  RECT            rect;

  SetCursor (NULL);
  mouse_forced = true;
  GetWindowRect (hwnd, &rect);
  center_x = rect.left + (rect.right - rect.left) / 2;
  center_y = rect.top + (rect.bottom - rect.top) / 2;
  SetCursorPos (center_x, center_y);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void MoveCursor (int x, int y)
{

  int             center_x;
  int             center_y;
  RECT            rect;

  SetCursor (NULL);
  mouse_forced = true;
  GetWindowRect (hwnd, &rect);
  center_x = rect.left + x;
  center_y = rect.top + y;
  SetCursorPos (center_x, center_y);

}

/*-----------------------------------------------------------------------------
                                    n o t e
-----------------------------------------------------------------------------*/

void WinPopup (char* message, ...)
{

  va_list  		marker;
  char        buf[1024];

  va_start (marker, message);
  vsprintf (buf, message, marker); 
  va_end (marker);
  MessageBox (NULL, buf, APP_TITLE, MB_ICONSTOP | MB_OK | 
    MB_TASKMODAL);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int WinWidth (void)
{

  return width;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void WinMousePosition (int* x, int* y)
{

  *x = select_pos.x;
  *y = select_pos.y;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int WinHeight (void)
{

  return height;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void WinTerm (void)
{
#if !SCREENAVER
  DestroyWindow (hwnd);
#endif
}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

HWND WinHwnd (void)
{

  return hwnd;

}


/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void AppQuit ()
{

  quit = true;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void AppUpdate ()
{

  CameraUpdate ();
  EntityUpdate ();
  WorldUpdate ();
  TextureUpdate ();
  VisibleUpdate ();
  CarUpdate ();
  RenderUpdate ();

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void AppInit (void)
{

  RandomInit (time (NULL));
  CameraInit ();
  RenderInit ();
  TextureInit ();
  WorldInit ();

}


/*-----------------------------------------------------------------------------
                                W i n M a i n
-----------------------------------------------------------------------------*/

void AppTerm (void) 
{

  TextureTerm ();
  WorldTerm ();
  RenderTerm ();
  CameraTerm ();
  WinTerm ();

}

/*-----------------------------------------------------------------------------
                                W i n M a i n
-----------------------------------------------------------------------------*/
#if !SCREENSAVER

int PASCAL WinMain (HINSTANCE instance_in, HINSTANCE previous_instance,
  LPSTR command_line, int show_style)
{

 	MSG		  msg;

  instance = instance_in;
  WinInit ();
  AppInit ();
  while (!quit) {
		if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))	{
			if (msg.message == WM_QUIT)	
				quit = true;
			else {
				TranslateMessage(&msg);			
				DispatchMessage(&msg);			
			}
    } else 
      AppUpdate ();

  }
  AppTerm ();
  return 0;

}

#else

BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; }
BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; }

#endif

LONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPARAM lparam)
{

  RECT            r;
  int             key;
  float           delta_x, delta_y;
  POINT           p;

  // Handles screen saver messages
  switch(message)
  {
  case WM_SIZE:
    width = LOWORD(lparam);  // width of client area 
    height = HIWORD(lparam); // height of client area 
    if (wparam == SIZE_MAXIMIZED) {
      IniIntSet ("WindowMaximized", 1);
    } else {
      IniIntSet ("WindowWidth", width);
      IniIntSet ("WindowHeight", height);
      IniIntSet ("WindowMaximized", 0);
    }
    RenderResize ();
    break;
  case WM_KEYDOWN:
    key = (int) wparam; 
    if (key == 'R')
      WorldReset (); 
    else if (key == 'W')
      RenderWireframeToggle ();
    else if (key == 'E')
      RenderEffectCycle ();
    else if (key == 'L')
      RenderLetterboxToggle ();
    else if (key == 'F')
      RenderFPSToggle ();
    else if (key == 'G')
      RenderFogToggle ();
    else if (key == 'T')
      RenderFlatToggle ();
    else if (key == VK_F1)
      RenderHelpToggle ();
    else if (key == VK_ESCAPE)
      break;
    else if (!SCREENSAVER) {
      //Dev mode keys
      if (key == 'C')
        CameraAutoToggle (); 
      if (key == 'B')
        CameraNextBehavior ();
      if (key == VK_F5)
        CameraReset ();
      if (key == VK_UP)
        CameraMedial (1.0f);
      if (key == VK_DOWN)
        CameraMedial (-1.0f);
      if (key == VK_LEFT)
        CameraLateral (1.0f);
      if (key == VK_RIGHT)
        CameraLateral (-1.0f);
      if (key == VK_PRIOR)
        CameraVertical (1.0f);
      if (key == VK_NEXT)
        CameraVertical (-1.0f);
      if (key == VK_F5)
        CameraReset ();
      return 0;
    } else
      break;
    return 0;
  case WM_MOVE:
    GetClientRect (hwnd, &r);
    height = r.bottom - r.top;
    width = r.right - r.left;
    IniIntSet ("WindowX", r.left);
    IniIntSet ("WindowY", r.top);
    IniIntSet ("WindowWidth", width);
    IniIntSet ("WindowHeight", height);
    half_width = width / 2;
    half_height = height / 2;
    return 0;
  case WM_LBUTTONDOWN:
    lmb = true;
    SetCapture (hwnd);
    break;
  case WM_RBUTTONDOWN:
    rmb = true;
    SetCapture (hwnd);
    break;
  case WM_LBUTTONUP:
    lmb = false;
    if (!rmb) {
      ReleaseCapture ();
      MoveCursor (select_pos.x, select_pos.y);
    }
    break;
  case WM_RBUTTONUP:
    rmb = false;
    if (!lmb) {
      ReleaseCapture ();
      MoveCursor (select_pos.x, select_pos.y);
    }
    break;
  case WM_MOUSEMOVE:
    p.x = LOWORD(lparam);  // horizontal position of cursor 
    p.y = HIWORD(lparam);  // vertical position of cursor 
    if (p.x < 0 || p.x > width)
      break;
    if (p.y < 0 || p.y > height)
      break;
    if (!mouse_forced && !lmb && !rmb) {
      select_pos = p; 
    }
    if (mouse_forced) {
      mouse_forced = false;
    } else if (rmb || lmb) {
      CenterCursor ();
      delta_x = (float)(mouse_pos.x - p.x) * MOUSE_MOVEMENT;
      delta_y = (float)(mouse_pos.y - p.y) * MOUSE_MOVEMENT;
      if (rmb && lmb) {
        GLvector    pos;
        CameraPan (delta_x);
        pos = CameraPosition ();
        pos.y += delta_y;
        CameraPositionSet (pos);
      } else if (rmb) {
        CameraPan (delta_x);
        CameraForward (delta_y);
      } else if (lmb) {
        GLvector    angle;
        angle = CameraAngle ();
        angle.y -= delta_x;
        angle.x += delta_y;
        CameraAngleSet (angle);
      }
    }
    mouse_pos = p;
    break;
  case WM_CREATE:
    hwnd = hwnd_in;
    if (SCREENSAVER)
      AppInit ();
    SetTimer (hwnd, 1, 7, NULL); 
    return 0;
  case WM_TIMER:
    AppUpdate ();
    return 0;
  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
#if SCREENSAVER
  return DefScreenSaverProc(hwnd_in,message,wparam,lparam);
#else
  return DefWindowProc (hwnd_in,message,wparam,lparam);   
#endif

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

bool WinInit (void)
{

  WNDCLASSEX    wcex;
  int           x, y;
  int           style;
  bool          max;

	wcex.cbSize         = sizeof(WNDCLASSEX); 
	wcex.style			    = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	  = (WNDPROC)ScreenSaverProc;
	wcex.cbClsExtra		  = 0;
	wcex.cbWndExtra		  = 0;
	wcex.hInstance		  = instance;
	wcex.hIcon			    = NULL;
	wcex.hCursor		    = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_BTNFACE+1);
	wcex.lpszMenuName	  = NULL;
	wcex.lpszClassName	= APP_TITLE;
	wcex.hIconSm		    = NULL;
  if (!RegisterClassEx(&wcex)) {
    WinPopup ("Cannot create window class");
    return false;
  }
  x = IniInt ("WindowX");
  y = IniInt ("WindowY");
  style = WS_TILEDWINDOW;
  style |= WS_MAXIMIZE;
  width = IniInt ("WindowWidth");
  height = IniInt ("WindowHeight");
  width = CLAMP (width, 800, 2048);
  height = CLAMP (height, 600, 2048);
  half_width = width / 2;
  half_height = height / 2;
  max = IniInt ("WindowMaximized") == 1;
  if (!(hwnd = CreateWindowEx (0, APP_TITLE, APP_TITLE, style,
    CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, instance, NULL))) {
    WinPopup ("Cannot create window");
    return false;
  }
  if (max) 
    ShowWindow (hwnd, SW_MAXIMIZE);
  else
    ShowWindow (hwnd, SW_SHOW);
  UpdateWindow (hwnd);
  return true;

}

================================================
FILE: Win.h
================================================
//Versioning info
#define APP_TITLE           "PixelCity"
#define APP                 "pixelcity"
#define VERSION_MAJOR       1
#define VERSION_MINOR       0
#define VERSION_REVISION    10
//Best to disable screensaver mode when working on the program.
#define SCREENSAVER         0
//Do we hide scene building behing a loading screen or show it?
#define LOADING_SCREEN      1
//Controls the density of cars.
#define CARS                500
//The "dead zone" along the edge of the world, with super-low detail.
#define WORLD_EDGE          200
//How often to rebuild the city
#define RESET_INTERVAL      (SCREENSAVER ? 120000 : 999999)//milliseconds
//How long the screen fade takes when transitioning to a new city
#define FADE_TIME           (SCREENSAVER ? 1500 : 1) //milliseconds
//Debug ground texture that shows traffic lanes
#define SHOW_DEBUG_GROUND   0
//Controls the ammount of space available for buildings.  
//Other code is wrtten assuming this will be a power of two.
#define WORLD_SIZE          1024
#define WORLD_HALF          (WORLD_SIZE / 2)
//Bitflags used to track how world space is being used.
#define CLAIM_ROAD          1
#define CLAIM_WALK          2
#define CLAIM_BUILDING      4
#define MAP_ROAD_NORTH      8
#define MAP_ROAD_SOUTH      16
#define MAP_ROAD_EAST       32
#define MAP_ROAD_WEST       64
//Random SATURATED color
#define RANDOM_COLOR          (glRgbaFromHsl ((float)RandomVal (255)/255,1.0f, 0.75f))
//Used in orienting roads and cars
enum
{
  NORTH,
  EAST,
  SOUTH,
  WEST
};

HWND  WinHwnd (void);
void  WinPopup (char* message, ...);
void  WinTerm (void);
bool  WinInit (void);
int   WinWidth (void);
int   WinHeight (void);
void  WinMousePosition (int* x, int* y);

================================================
FILE: World.cpp
================================================
/*-----------------------------------------------------------------------------

  World.cpp

  2009 Shamus Young

-------------------------------------------------------------------------------

  This holds a bunch of variables used by the other modules. It has the 
  claim system, which tracks all of the "property" is being used: As roads,
  buildings, etc. 

-----------------------------------------------------------------------------*/

#define HUE_COUNT         (sizeof(hue_list)/sizeof(float))
#define LIGHT_COLOR_COUNT (sizeof(light_colors)/sizeof(HSL))

#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
#include <math.h>
#include <time.h>
#include <vector>

#include "glTypes.h"
#include "building.h"
#include "car.h"
#include "deco.h"
#include "camera.h"
#include "light.h"
#include "macro.h"
#include "math.h"
#include "mesh.h"
#include "random.h"
#include "render.h"
#include "sky.h"
#include "texture.h"
#include "visible.h"
#include "win.h"
#include "world.h"

using namespace std;

struct plot
{
  int             x;
  int             z;
  int             width;
  int             depth;

};

enum {
  FADE_IDLE,
  FADE_OUT,
  FADE_WAIT,
  FADE_IN,
};

struct HSL
{
  float     hue;
  float     sat;
  float     lum;
};

class CStreet
{
public:
  int                 _x;
  int                 _y;
  int                 _width;
  int                 _depth;
  CMesh*              _mesh;
  
  CStreet (int x, int y, int width, int depth);
  ~CStreet();
  void                Render ();

};

static HSL            light_colors[] = 
{ 
  0.04f,  0.9f,  0.93f,   //Amber / pink
  0.055f, 0.95f, 0.93f,   //Slightly brighter amber 
  0.08f,  0.7f,  0.93f,   //Very pale amber
  0.07f,  0.9f,  0.93f,   //Very pale orange
  0.1f,   0.9f,  0.85f,   //Peach
  0.13f,  0.9f,  0.93f,   //Pale Yellow
  0.15f,  0.9f,  0.93f,   //Yellow
  0.17f,  1.0f,  0.85f,   //Saturated Yellow
  0.55f,  0.9f,  0.93f,   //Cyan
  0.55f,  0.9f,  0.93f,   //Cyan - pale, almost white
  0.6f,   0.9f,  0.93f,   //Pale blue
  0.65f,  0.9f,  0.93f,   //Pale Blue II, The Palening
  0.65f,  0.4f,  0.99f,   //Pure white. Bo-ring.
  0.65f,  0.0f,  0.8f,    //Dimmer white.
  0.65f,  0.0f,  0.6f,    //Dimmest white.
}; 

static float          hue_list[] = { 0.04f, 0.07f, 0.1f, 0.5f, 0.6f }; //Yellows and blues - good for lights
static GLrgba         bloom_color;
static long           last_update;
static char           world[WORLD_SIZE][WORLD_SIZE];
static CSky*          sky;
static int            fade_state;
static unsigned       fade_start;
static float          fade_current;
static int            modern_count;
static int            tower_count;
static int            blocky_count;
static bool           reset_needed;
static int            skyscrapers;
static GLbbox         hot_zone;
static int            logo_index;
static unsigned       start_time;
static int            scene_begin;

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static GLrgba get_light_color (float sat, float lum)
{

  int     index;

  index = RandomVal (LIGHT_COLOR_COUNT);
  return glRgbaFromHsl (light_colors[index].hue, sat, lum);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void claim (int x, int y, int width, int depth, int val)
{

  int     xx, yy;

  for (xx = x; xx < (x + width); xx++) {
    for (yy = y; yy < (y + depth); yy++) {
      world[CLAMP (xx,0,WORLD_SIZE - 1)][CLAMP (yy,0,WORLD_SIZE - 1)] |= val;
    }
  }

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static bool claimed (int x, int y, int width, int depth)
{

  int     xx, yy;

  for (xx = x; xx < x + width; xx++) {
    for (yy = y; yy < y + depth; yy++) {
      if (world[CLAMP (xx,0,WORLD_SIZE - 1)][CLAMP (yy,0,WORLD_SIZE - 1)])
        return true;
    }
  }
  return false;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void build_road (int x1, int y1, int width, int depth)
{

  int       lanes;
  int       divider;
  int       sidewalk;

  //the given rectangle defines a street and its sidewalk. See which way it goes.
  if (width > depth) 
    lanes = depth;
  else
    lanes = width;
  //if we dont have room for both lanes and sidewalk, abort
  if (lanes < 4)
    return;
  //if we have an odd number of lanes, give the extra to a divider.
  if (lanes % 2) {
    lanes--;
    divider = 1;
  } else
    divider = 0;
  //no more than 10 traffic lanes, give the rest to sidewalks
  sidewalk = MAX (2, (lanes - 10));
  lanes -= sidewalk;
  sidewalk /= 2;
  //take the remaining space and give half to each direction
  lanes /= 2;
  //Mark the entire rectangle as used
  claim (x1, y1, width, depth, CLAIM_WALK);
  //now place the directional roads
  if (width > depth) {
    claim (x1, y1 + sidewalk, width, lanes, CLAIM_ROAD | MAP_ROAD_WEST);
    claim (x1, y1 + sidewalk + lanes + divider, width, lanes, CLAIM_ROAD | MAP_ROAD_EAST);
  } else {
    claim (x1 + sidewalk, y1, lanes, depth, CLAIM_ROAD | MAP_ROAD_SOUTH);
    claim (x1 + sidewalk + lanes + divider, y1, lanes, depth, CLAIM_ROAD | MAP_ROAD_NORTH);
  }

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static plot find_plot (int x, int z)
{

  plot      p;
  int       x1, x2, z1, z2;

  //We've been given the location of an open bit of land, but we have no 
  //idea how big it is. Find the boundary.
  x1 = x2 = x;
  while (!claimed (x1 - 1, z, 1, 1) && x1 > 0)
    x1--;
  while (!claimed (x2 + 1, z, 1, 1) && x2 < WORLD_SIZE)
    x2++;
  z1 = z2 = z;
  while (!claimed (x, z1 - 1, 1, 1) && z1 > 0)
    z1--;
  while (!claimed (x, z2 + 1, 1, 1) && z2 < WORLD_SIZE)
    z2++;
  p.width = (x2 - x1);
  p.depth = (z2 - z1);
  p.x = x1;
  p.z = z1;
  return p;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static plot make_plot (int x, int z, int width, int depth)
{

  plot      p = {x, z, width, depth};
  return p;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

void do_building (plot p)
{

  int     height;
  int     seed;
  int     area;
  int     type;
  GLrgba  color;
  bool    square;

  //now we know how big the rectangle plot is. 
  area = p.width * p.depth;
  color = WorldLightColor (RandomVal ());
  seed = RandomVal ();
  //Make sure the plot is big enough for a building
  if (p.width < 10 || p.depth < 10)
    return;
  //If the area is too big for one building, sub-divide it.
 
  if (area > 800) {
    if (COIN_FLIP) {
      p.width /= 2;
      if (COIN_FLIP)
        do_building (make_plot (p.x, p.z, p.width, p.depth));
      else
        do_building (make_plot (p.x + p.width, p.z, p.width, p.depth));
      return;
    } else {
      p.depth /= 2;
      if (COIN_FLIP)
        do_building (make_plot (p.x, p.z, p.width, p.depth));
      else
        do_building (make_plot (p.x, p.z + p.depth, p.width, p.depth));
      return;
    }
  }
  if (area < 100)
    return;
  //The plot is "square" if width & depth are close
  square = abs (p.width - p.depth) < 10;
  //mark the land as used so other buildings don't appear here, even if we don't use it all.
  claim (p.x, p.z, p.width, p.depth, CLAIM_BUILDING);
  
  //The roundy mod buildings look best on square plots.
  if (square && p.width > 20) {
    height = 45 + RandomVal (10);
    modern_count++;
    skyscrapers++;
    new CBuilding (BUILDING_MODERN, p.x, p.z, height, p.width, p.depth, seed, color);
    return;
  }
  /*
  //Rectangular plots are a good place for Blocky style buildsing to sprawl blockily.
  if (p.width > p.depth * 2 || p.depth > p.width * 2 && area > 800) {
    height = 20 + RandomVal (10);
    blocky_count++;
    skyscrapers++;
    new CBuilding (BUILDING_BLOCKY, p.x, p.z, height, p.width, p.depth, seed, color);
    return;
  }
  */
  //tower_count = -1;
  //This spot isn't ideal for any particular building, but try to keep a good mix
  if (tower_count < modern_count && tower_count < blocky_count) {
    type = BUILDING_TOWER;
    tower_count++;
  } else if (blocky_count < modern_count) {
    type = BUILDING_BLOCKY;
    blocky_count++;
  } else {
    type = BUILDING_MODERN;
    modern_count++;
  }
  height = 45 + RandomVal (10);
  new CBuilding (type, p.x, p.z, height, p.width, p.depth, seed, color);
  skyscrapers++;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static int build_light_strip (int x1, int z1, int direction)
{

  CDeco*  d;
  GLrgba  color;
  int     x2, z2;
  int     length;
  int     width, depth;
  int     dir_x, dir_z;
  float   size_adjust;
  
  //We adjust the size of the lights with this.  
  size_adjust = 2.5f;
  color = glRgbaFromHsl (0.09f,  0.99f,  0.85f);
  switch (direction) {
  case NORTH:
    dir_z = 1; dir_x = 0;break;
  case SOUTH:
    dir_z = 1; dir_x = 0;break;
  case EAST:
    dir_z = 0; dir_x = 1;break;
  case WEST:
    dir_z = 0; dir_x = 1;break;
  }
  //So we know we're on the corner of an intersection
  //look in the given  until we reach the end of the sidewalk
  x2 = x1;
  z2 = z1;
  length = 0;
  while (x2 > 0 && x2 < WORLD_SIZE && z2 > 0 && z2 < WORLD_SIZE) {
    if ((world[x2][z2] & CLAIM_ROAD))
      break;
    length++;
    x2 += dir_x;
    z2 += dir_z;
  }
  if (length < 10)
    return length;
  width = MAX (abs(x2 - x1), 1);
  depth = MAX (abs(z2 - z1), 1);
  d = new CDeco;
  if (direction == EAST)
    d->CreateLightStrip ((float)x1, (float)z1 - size_adjust, (float)width, (float)depth + size_adjust, 2, color);
  else if (direction == WEST)
    d->CreateLightStrip ((float)x1, (float)z1, (float)width, (float)depth + size_adjust, 2, color);
  else if (direction == NORTH)
    d->CreateLightStrip ((float)x1, (float)z1, (float)width + size_adjust, (float)depth, 2, color);
  else
    d->CreateLightStrip ((float)x1 - size_adjust, (float)z1, (float)width + size_adjust, (float)depth, 2, color);
  return length;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

static void do_reset (void)
{
  
  int       x, y;
  int       width, depth, height;
  int       attempts;
  bool      broadway_done;
  bool      road_left, road_right;
  GLrgba    light_color;
  GLrgba    building_color;
  float     west_street, north_street, east_street, south_street;

  //Re-init Random to make the same city each time. Helpful when running tests.
  RandomInit (6);
  reset_needed = false;
  broadway_done = false;
  skyscrapers = 0;
  logo_index = 0;
  scene_begin = 0;
  tower_count = blocky_count = modern_count = 0;
  hot_zone = glBboxClear ();
  EntityClear ();
  LightClear ();
  CarClear ();
  TextureReset ();
  //Pick a tint for the bloom 
  bloom_color = get_light_color(0.5f + (float)RandomVal (10) / 20.0f, 0.75f);
  light_color = glRgbaFromHsl (0.11f, 1.0f, 0.65f);
  ZeroMemory (world, WORLD_SIZE * WORLD_SIZE);
  for (y = WORLD_EDGE; y < WORLD_SIZE - WORLD_EDGE; y += RandomVal (25) + 25) {
    if (!broadway_done && y > WORLD_HALF - 20) {
      build_road (0, y, WORLD_SIZE, 19);
      y += 20;
      broadway_done = true;
    } else {
      depth = 6 + RandomVal (6);
      if (y < WORLD_HALF / 2)
        north_street = (float)(y + depth / 2);
      if (y < (WORLD_SIZE - WORLD_HALF / 2))
        south_street = (float)(y + depth / 2);
      build_road (0, y, WORLD_SIZE, depth);
    }
  }

  broadway_done = false;
  for (x = WORLD_EDGE; x < WORLD_SIZE - WORLD_EDGE; x += RandomVal (25) + 25) {
    if (!broadway_done && x > WORLD_HALF - 20) {
      build_road (x, 0, 19, WORLD_SIZE);
      x += 20;
      broadway_done = true;
    } else {
      width = 6 + RandomVal (6);
      if (x <= WORLD_HALF / 2)
        west_street = (float)(x + width / 2);
      if (x <= WORLD_HALF + WORLD_HALF / 2)
        east_street = (float)(x + width / 2);
      build_road (x, 0, width, WORLD_SIZE);
    }
  }
  //We kept track of the positions of streets that will outline the high-detail hot zone 
  //in the middle of the world.  Save this in a bounding box so that later we can 
  //have the camera fly around without clipping through buildings.
  hot_zone = glBboxContainPoint (hot_zone, glVector (west_street, 0.0f, north_street)); 
  hot_zone = glBboxContainPoint (hot_zone, glVector (east_street, 0.0f, south_street));
  
  //Scan for places to put runs of streetlights on the east & west side of the road
  for (x = 1; x < WORLD_SIZE - 1; x++) {
    for (y = 0; y < WORLD_SIZE; y++) {
      //if this isn't a bit of sidewalk, then keep looking
      if (!(world[x][y] & CLAIM_WALK))
        continue;
      //If it's used as a road, skip it.
      if ((world[x][y] & CLAIM_ROAD))
        continue;
      road_left = (world[x + 1][y] & CLAIM_ROAD) != 0;
      road_right = (world[x - 1][y] & CLAIM_ROAD) != 0;
      //if the cells to our east and west are not road, then we're not on a corner. 
      if (!road_left && !road_right)
        continue;
      //if the cell to our east AND west is road, then we're on a median. skip it
      if (road_left && road_right)
        continue;
      y += build_light_strip (x, y, road_right ? SOUTH : NORTH);
    }
  }
  //Scan for places to put runs of streetlights on the north & south side of the road
  for (y = 1; y < WORLD_SIZE - 1; y++) {
    for (x = 1; x < WORLD_SIZE - 1; x++) {
      //if this isn't a bit of sidewalk, then keep looking
      if (!(world[x][y] & CLAIM_WALK))
        continue;
      //If it's used as a road, skip it.
      if ((world[x][y] & CLAIM_ROAD))
        continue;
      road_left = (world[x][y + 1] & CLAIM_ROAD) != 0;
      road_right = (world[x][y - 1] & CLAIM_ROAD) != 0;
      //if the cell to our east AND west is road, then we're on a median. skip it
      if (road_left && road_right)
        continue;
      //if the cells to our north and south are not road, then we're not on a corner. 
      if (!road_left && !road_right)
        continue;
      x += build_light_strip (x, y, road_right ? EAST : WEST);
    }
  }
  
  
  //Scan over the center area of the map and place the big buildings 
  attempts = 0;
   while (skyscrapers < 50 && attempts < 350) {
    x = (WORLD_HALF / 2) + (RandomVal () % WORLD_HALF);
    y = (WORLD_HALF / 2) + (RandomVal () % WORLD_HALF);
    if (!claimed (x, y, 1,1)) {
      do_building (find_plot (x, y));
      skyscrapers++;
    }
    attempts++;
  }
  
  //now blanket the rest of the world with lesser buildings
  for (x = 0; x < WORLD_SIZE; x ++) {
    for (y = 0; y < WORLD_SIZE; y ++) {
      if (world[CLAMP (x,0,WORLD_SIZE)][CLAMP (y,0,WORLD_SIZE)])
        continue;
      width = 12 + RandomVal (20);
      depth = 12 + RandomVal (20);
      height = MIN (width, depth);
      if (x < 30 || y < 30 || x > WORLD_SIZE - 30 || y > WORLD_SIZE - 30)
        height = RandomVal (15) + 20;
      else if (x < WORLD_HALF / 2)
        height /= 2;
      while (width > 8 && depth > 8) {
        if (!claimed (x, y, width, depth)) {
          claim (x, y, width, depth,CLAIM_BUILDING);
          building_color = WorldLightColor (RandomVal ());
          //if we're out of the hot zone, use simple buildings
          if (x < hot_zone.min.x || x > hot_zone.max.x || y < hot_zone.min.z || y > hot_zone.max.z) {
            height = 5 + RandomVal (height) + RandomVal (height);
            new CBuilding (BUILDING_SIMPLE, x + 1, y + 1, height, width - 2, depth - 2, RandomVal (), building_color);
          } else { //use fancy buildings.
            height = 15 + RandomVal (15);
            width -=2;
            depth -=2;
            if (COIN_FLIP) 
              new CBuilding (BUILDING_TOWER, x + 1, y + 1, height, width, depth, RandomVal (), building_color);
            else
              new CBuilding (BUILDING_BLOCKY, x + 1, y + 1, height, width, depth, RandomVal (), building_color);
          }
          break;
        }
        width--;
        depth--;
      }
      //leave big gaps near the edge of the map, no need to pack detail there.
      if (y < WORLD_EDGE || y > WORLD_SIZE - WORLD_EDGE) 
        y += 32;
    }
    //leave big gaps near the edge of the map
    if (x < WORLD_EDGE || x > WORLD_SIZE - WORLD_EDGE) 
      x += 28;
  }
  

}

/*-----------------------------------------------------------------------------

  This will return a random color which is suitible for light sources, taken
  from a narrow group of hues. (Yellows, oranges, blues.)

-----------------------------------------------------------------------------*/

GLrgba WorldLightColor (unsigned index)
{

  index %= LIGHT_COLOR_COUNT;
  return glRgbaFromHsl (light_colors[index].hue, light_colors[index].sat, light_colors[index].lum);

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

char WorldCell (int x, int y)
{

  return world[CLAMP (x, 0,WORLD_SIZE - 1)][CLAMP (y, 0, WORLD_SIZE - 1)];

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

GLrgba WorldBloomColor ()
{

  return bloom_color;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

int WorldLogoIndex ()
{

  return logo_index++;

}

/*-----------------------------------------------------------------------------

-----------------------------------------------------------------------------*/

GLbbox WorldHotZone ()
{

  return hot_zone;

}

/*-----------------------------------------------------------------------------

------------------------------------------------
Download .txt
gitextract_5n_ku7qe/

├── Building.cpp
├── Building.h
├── Camera.cpp
├── Camera.h
├── Car.cpp
├── Car.h
├── Deco.cpp
├── Deco.h
├── Entity.cpp
├── Entity.h
├── Ini.cpp
├── Ini.h
├── Light.cpp
├── Light.h
├── Macro.h
├── Math.cpp
├── Math.h
├── Mesh.cpp
├── Mesh.h
├── PixelCity.dsp
├── Random.cpp
├── Random.h
├── Render.cpp
├── Render.h
├── Sky.cpp
├── Sky.h
├── Texture.cpp
├── Texture.h
├── Visible.cpp
├── Visible.h
├── Win.cpp
├── Win.h
├── World.cpp
├── World.h
├── glBbox.cpp
├── glMatrix.cpp
├── glQuat.cpp
├── glRgba.cpp
├── glTypes.h
├── glVector2.cpp
└── glVector3.cpp
Download .txt
SYMBOL INDEX (231 symbols across 27 files)

FILE: Building.h
  function class (line 13) | class CBuilding : public CEntity

FILE: Camera.cpp
  function GLvector (line 65) | static GLvector flycam_position (unsigned t)
  function do_auto_cam (line 105) | static void do_auto_cam ()
  function CameraAutoToggle (line 181) | void CameraAutoToggle ()
  function CameraNextBehavior (line 192) | void CameraNextBehavior ()
  function CameraYaw (line 204) | void CameraYaw (float delta)
  function CameraPitch (line 215) | void CameraPitch (float delta)
  function CameraPan (line 226) | void CameraPan (float delta)
  function CameraForward (line 242) | void CameraForward (float delta)
  function CameraVertical (line 258) | void CameraVertical (float val)
  function CameraLateral (line 270) | void CameraLateral (float val)
  function CameraMedial (line 282) | void CameraMedial (float val)
  function GLvector (line 294) | GLvector CameraPosition (void)
  function CameraReset (line 307) | void CameraReset ()
  function CameraPositionSet (line 323) | void CameraPositionSet (GLvector new_pos)
  function GLvector (line 334) | GLvector CameraAngle (void)
  function CameraAngleSet (line 347) | void CameraAngleSet (GLvector new_angle)
  function CameraInit (line 359) | void CameraInit (void)
  function CameraUpdate (line 371) | void CameraUpdate (void)
  function CameraTerm (line 396) | void CameraTerm (void)

FILE: Car.cpp
  function CarCount (line 60) | int CarCount ()
  function CarClear (line 71) | void CarClear ()
  function CarRender (line 87) | void CarRender ()
  function CarUpdate (line 115) | void CarUpdate ()

FILE: Car.h
  function class (line 1) | class CCar

FILE: Deco.h
  function class (line 5) | class CDeco : CEntity

FILE: Entity.cpp
  type entity (line 31) | struct entity
  type cell (line 37) | struct cell
  function do_compare (line 61) | static int do_compare (const void *arg1, const void *arg2 )
  function add (line 83) | void add (CEntity* b)
  function do_compile (line 97) | static void do_compile ()
  function EntityReady (line 188) | bool EntityReady ()
  function EntityProgress (line 199) | float EntityProgress ()
  function EntityUpdate (line 211) | void EntityUpdate ()
  function EntityRender (line 239) | void EntityRender ()
  function EntityClear (line 300) | void EntityClear ()
  function EntityCount (line 338) | int EntityCount ()
  function EntityInit (line 349) | void EntityInit (void)
  function EntityPolyCount (line 358) | int EntityPolyCount (void)

FILE: Entity.h
  function class (line 9) | class CEntity

FILE: Ini.cpp
  function IniInt (line 33) | int IniInt (char* entry)
  function IniIntSet (line 47) | void IniIntSet (char* entry, int val)
  function IniFloat (line 61) | float IniFloat (char* entry)
  function IniFloatSet (line 76) | void IniFloatSet (char* entry, float val)
  function IniStringSet (line 103) | void IniStringSet (char* entry, char* val)
  function IniVectorSet (line 115) | void IniVectorSet (char* entry, GLvector v)
  function GLvector (line 127) | GLvector IniVector (char* entry)

FILE: Light.cpp
  function LightClear (line 45) | void LightClear ()
  function LightCount (line 63) | int LightCount ()
  function LightRender (line 75) | void LightRender ()

FILE: Light.h
  function class (line 1) | class CLight

FILE: Math.cpp
  function MathAngle (line 22) | float MathAngle (float angle)
  function MathAngle (line 37) | float MathAngle (float x1, float y1, float x2, float y2)
  function MathDistance2 (line 71) | float MathDistance2 (float x1, float y1, float x2, float y2)
  function MathDistance (line 88) | float MathDistance (float x1, float y1, float x2, float y2)
  function MathAngleDifference (line 104) | float MathAngleDifference (float a1, float a2)
  function MathInterpolate (line 123) | float MathInterpolate (float n1, float n2, float delta)
  function MathSmoothStep (line 134) | float MathSmoothStep (float val, float a, float b)
  function MathAverage (line 149) | float MathAverage (float n1, float n2)
  function MathScalarCurve (line 162) | float MathScalarCurve (float val)

FILE: Mesh.h
  type cube (line 4) | struct cube
  type quad_strip (line 9) | struct quad_strip
  type fan (line 14) | struct fan
  function class (line 19) | class CMesh

FILE: Random.cpp
  function RandomVal (line 37) | unsigned long RandomVal (void)
  function RandomVal (line 68) | unsigned long RandomVal (int range)
  function RandomInit (line 79) | void RandomInit (unsigned long seed)

FILE: Render.cpp
  type glFont (line 82) | struct glFont
  function do_progress (line 147) | static void do_progress (float center_x, float center_y, float radius, f...
  function do_effects (line 205) | static void do_effects (int type)
  function RenderMaxTextureSize (line 363) | int RenderMaxTextureSize ()
  function RenderPrint (line 378) | void RenderPrint (int x, int y, int font, GLrgba color, const char *fmt,...
  function RenderPrint (line 402) | void RenderPrint (int line, const char *fmt, ...)
  function do_help (line 443) | void static do_help (void)
  function do_fps (line 468) | void do_fps ()
  function RenderResize (line 482) | void RenderResize (void)
  function RenderTerm (line 511) | void RenderTerm (void)
  function RenderInit (line 525) | void RenderInit (void)
  function RenderFPSToggle (line 583) | void RenderFPSToggle ()
  function RenderFog (line 595) | bool RenderFog ()
  function RenderFogToggle (line 606) | void RenderFogToggle ()
  function RenderLetterboxToggle (line 618) | void RenderLetterboxToggle ()
  function RenderWireframeToggle (line 632) | void RenderWireframeToggle ()
  function RenderWireframe (line 644) | bool RenderWireframe ()
  function RenderEffectCycle (line 656) | void RenderEffectCycle ()
  function RenderBloom (line 668) | bool RenderBloom ()
  function RenderFlat (line 680) | bool RenderFlat ()
  function RenderFlatToggle (line 691) | void RenderFlatToggle ()
  function RenderHelpToggle (line 703) | void RenderHelpToggle ()
  function RenderFogDistance (line 714) | float RenderFogDistance ()
  function RenderFogFX (line 729) | void RenderFogFX (float scalar)
  function RenderUpdate (line 746) | void RenderUpdate (void)

FILE: Sky.cpp
  function SkyRender (line 37) | void SkyRender ()
  function SkyClear (line 49) | void SkyClear ()

FILE: Sky.h
  type sky_point (line 4) | struct sky_point
  function class (line 10) | class CSky

FILE: Texture.cpp
  class CTexture (line 129) | class CTexture
    method Clear (line 145) | void              Clear () { _ready = false; }
  function drawrect_simple (line 163) | void drawrect_simple (int left, int top, int right, int bottom, GLrgba c...
  function drawrect_simple (line 181) | void drawrect_simple (int left, int top, int right, int bottom, GLrgba c...
  function drawrect (line 202) | void drawrect (int left, int top, int right, int bottom, GLrgba color)
  function window (line 288) | static void window (int x, int y, int size, int id, GLrgba color)
  function do_bloom (line 341) | static void do_bloom (CTexture* t)
  function TextureId (line 757) | unsigned TextureId (int id)
  function TextureRandomBuilding (line 772) | unsigned TextureRandomBuilding (int index)
  function TextureReset (line 784) | void TextureReset (void)
  function TextureReady (line 801) | bool TextureReady ()
  function TextureUpdate (line 812) | void TextureUpdate (void)
  function TextureTerm (line 841) | void TextureTerm (void)
  function TextureInit (line 858) | void TextureInit (void)

FILE: Visible.cpp
  function Visible (line 35) | bool Visible (GLvector pos)
  function Visible (line 47) | bool Visible (int x, int z)
  function VisibleUpdate (line 60) | void VisibleUpdate (void)

FILE: Win.cpp
  function CenterCursor (line 65) | static void CenterCursor ()
  function MoveCursor (line 85) | static void MoveCursor (int x, int y)
  function WinPopup (line 105) | void WinPopup (char* message, ...)
  function WinWidth (line 123) | int WinWidth (void)
  function WinMousePosition (line 134) | void WinMousePosition (int* x, int* y)
  function WinHeight (line 147) | int WinHeight (void)
  function WinTerm (line 158) | void WinTerm (void)
  function HWND (line 169) | HWND WinHwnd (void)
  function AppQuit (line 181) | void AppQuit ()
  function AppUpdate (line 192) | void AppUpdate ()
  function AppInit (line 209) | void AppInit (void)
  function AppTerm (line 225) | void AppTerm (void)
  function WinMain (line 241) | int PASCAL WinMain (HINSTANCE instance_in, HINSTANCE previous_instance,
  function BOOL (line 269) | BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT msg, WPARAM wPar...
  function BOOL (line 270) | BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; }
  function LONG (line 274) | LONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPAR...
  function WinInit (line 436) | bool WinInit (void)

FILE: World.cpp
  type plot (line 45) | struct plot
  type HSL (line 61) | struct HSL
  class CStreet (line 68) | class CStreet
  function GLrgba (line 124) | static GLrgba get_light_color (float sat, float lum)
  function claim (line 138) | static void claim (int x, int y, int width, int depth, int val)
  function claimed (line 155) | static bool claimed (int x, int y, int width, int depth)
  function build_road (line 174) | static void build_road (int x1, int y1, int width, int depth)
  function plot (line 218) | static plot find_plot (int x, int z)
  function plot (line 248) | static plot make_plot (int x, int z, int width, int depth)
  function do_building (line 260) | void do_building (plot p)
  function build_light_strip (line 343) | static int build_light_strip (int x1, int z1, int direction)
  function do_reset (line 400) | static void do_reset (void)
  function GLrgba (line 572) | GLrgba WorldLightColor (unsigned index)
  function WorldCell (line 584) | char WorldCell (int x, int y)
  function GLrgba (line 595) | GLrgba WorldBloomColor ()
  function WorldLogoIndex (line 606) | int WorldLogoIndex ()
  function GLbbox (line 617) | GLbbox WorldHotZone ()
  function WorldTerm (line 628) | void WorldTerm (void)
  function WorldReset (line 638) | void WorldReset (void)
  function WorldRender (line 656) | void WorldRender ()
  function WorldFade (line 684) | float WorldFade (void)
  function WorldSceneBegin (line 695) | int WorldSceneBegin ()
  function WorldSceneElapsed (line 708) | int WorldSceneElapsed ()
  function WorldUpdate (line 726) | void WorldUpdate (void)
  function WorldInit (line 778) | void WorldInit (void)

FILE: glBbox.cpp
  function glBboxTestPoint (line 25) | bool glBboxTestPoint (GLbbox box, GLvector point)
  function GLbbox (line 42) | GLbbox glBboxContainPoint (GLbbox box, GLvector point)
  function GLbbox (line 59) | GLbbox glBboxClear (void)

FILE: glMatrix.cpp
  function GLmatrix (line 117) | GLmatrix glMatrixIdentity (void)
  function glMatrixElementsSet (line 137) | void glMatrixElementsSet (GLmatrix* m, float* in)
  function GLmatrix (line 166) | GLmatrix glMatrixMultiply (GLmatrix a, GLmatrix b)
  function GLvector (line 193) | GLvector glMatrixTransformPoint (GLmatrix m, GLvector in)
  function GLmatrix (line 209) | GLmatrix glMatrixTranslate (GLmatrix m, GLvector in)
  function GLmatrix (line 235) | GLmatrix glMatrixRotate (GLmatrix m, float theta, float x, float y, floa...
  function GLvector (line 277) | GLvector glMatrixToEuler (GLmatrix mat, int order)

FILE: glQuat.cpp
  type QuatPart (line 21) | enum QuatPart {X, Y, Z, W}
  function GLquat (line 27) | GLquat glQuat (float x, float y, float z, float w)
  function GLvector (line 60) | GLvector glQuatToEuler (GLquat q, int order)

FILE: glRgba.cpp
  function GLrgba (line 26) | GLrgba glRgbaFromHsl (float h, float sl, float l)
  function GLrgba (line 80) | GLrgba glRgbaInterpolate (GLrgba c1, GLrgba c2, float delta)
  function GLrgba (line 97) | GLrgba glRgbaAdd (GLrgba c1, GLrgba c2)
  function GLrgba (line 113) | GLrgba glRgbaSubtract (GLrgba c1, GLrgba c2)
  function GLrgba (line 130) | GLrgba glRgbaMultiply (GLrgba c1, GLrgba c2)
  function GLrgba (line 146) | GLrgba glRgbaScale (GLrgba c, float scale)
  function GLrgba (line 160) | GLrgba glRgba (char* string)
  function GLrgba (line 185) | GLrgba glRgba (int red, int green, int blue)
  function GLrgba (line 202) | GLrgba glRgba (float red, float green, float blue)
  function GLrgba (line 219) | GLrgba glRgba (float red, float green, float blue, float alpha)
  function GLrgba (line 237) | GLrgba glRgba (long c)
  function GLrgba (line 254) | GLrgba glRgba (float luminance)
  function GLrgba (line 273) | GLrgba glRgbaUnique (int i)
  function GLrgba (line 290) | GLrgba GLrgba::operator+ (const GLrgba& c)
  function GLrgba (line 295) | GLrgba GLrgba::operator+ (const float& c)
  function GLrgba (line 318) | GLrgba GLrgba::operator- (const GLrgba& c)
  function GLrgba (line 323) | GLrgba GLrgba::operator- (const float& c)
  function GLrgba (line 346) | GLrgba GLrgba::operator* (const GLrgba& c)
  function GLrgba (line 351) | GLrgba GLrgba::operator* (const float& c)
  function GLrgba (line 374) | GLrgba GLrgba::operator/ (const GLrgba& c)
  function GLrgba (line 379) | GLrgba GLrgba::operator/ (const float& c)

FILE: glTypes.h
  type GLquat (line 28) | struct GLquat
  type GLvector (line 36) | struct GLvector
  type GLvector (line 44) | typedef GLvector       GLvector3;
  type GLvector2 (line 46) | struct GLvector2
  type GLrgba (line 53) | struct GLrgba
  type GLmatrix (line 62) | struct GLmatrix
  type GLbbox (line 67) | struct GLbbox
  type GLvertex (line 73) | struct GLvertex
  type GLrect (line 81) | struct GLrect
  type GLtriangle (line 89) | struct GLtriangle

FILE: glVector2.cpp
  function GLvector2 (line 26) | GLvector2 glVectorNormalize (GLvector2 v)
  function glVectorLength (line 42) | float glVectorLength (GLvector2 v)
  function GLvector2 (line 53) | GLvector2 glVectorSinCos (float a)
  function GLvector2 (line 69) | GLvector2 glVector (float x, float y)
  function GLvector2 (line 84) | GLvector2 glVectorAdd (GLvector2 val1, GLvector2 val2)
  function GLvector2 (line 100) | GLvector2 glVectorInterpolate (GLvector2 v1, GLvector2 v2, float scalar)
  function GLvector2 (line 115) | GLvector2 glVectorSubtract (GLvector2 val1, GLvector2 val2)
  function GLvector2 (line 130) | GLvector2 GLvector2::operator+ (const GLvector2& c)
  function GLvector2 (line 135) | GLvector2 GLvector2::operator+ (const float& c)
  function GLvector2 (line 152) | GLvector2 GLvector2::operator- (const GLvector2& c)
  function GLvector2 (line 157) | GLvector2 GLvector2::operator- (const float& c)
  function GLvector2 (line 174) | GLvector2 GLvector2::operator* (const GLvector2& c)
  function GLvector2 (line 179) | GLvector2 GLvector2::operator* (const float& c)
  function GLvector2 (line 196) | GLvector2 GLvector2::operator/ (const GLvector2& c)
  function GLvector2 (line 201) | GLvector2 GLvector2::operator/ (const float& c)

FILE: glVector3.cpp
  function GLvector (line 26) | GLvector glVectorReflect (GLvector3 ray, GLvector3 normal)
  function GLvector3 (line 41) | GLvector3 glVector (float x, float y, float z)
  function GLvector3 (line 57) | GLvector3 glVectorInterpolate (GLvector3 v1, GLvector3 v2, float scalar)
  function glVectorLength (line 73) | float glVectorLength (GLvector3 v)
  function glVectorDotProduct (line 84) | float glVectorDotProduct (GLvector3 v1, GLvector3 v2)
  function GLvector3 (line 95) | GLvector3 glVectorCrossProduct (GLvector3 v1, GLvector3 v2)
  function GLvector3 (line 111) | GLvector3 glVectorInvert (GLvector3 v)
  function GLvector3 (line 125) | GLvector3 glVectorScale (GLvector3 v, float scale)
  function GLvector3 (line 139) | GLvector3 glVectorNormalize (GLvector3 v)
  function GLvector (line 155) | GLvector GLvector::operator+ (const GLvector& c)
  function GLvector (line 160) | GLvector GLvector::operator+ (const float& c)
  function GLvector (line 179) | GLvector GLvector::operator- (const GLvector& c)
  function GLvector (line 184) | GLvector GLvector::operator- (const float& c)
  function GLvector (line 203) | GLvector GLvector::operator* (const GLvector& c)
  function GLvector (line 208) | GLvector GLvector::operator* (const float& c)
  function GLvector (line 227) | GLvector GLvector::operator/ (const GLvector& c)
  function GLvector (line 232) | GLvector GLvector::operator/ (const float& c)
Condensed preview — 41 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (261K chars).
[
  {
    "path": "Building.cpp",
    "chars": 28537,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Building.cpp\r\n\r\n  2009 Shamus Young"
  },
  {
    "path": "Building.h",
    "chars": 1893,
    "preview": "#ifndef ENTITY\r\n#include \"entity.h\"\r\n#endif\r\n\r\nenum\r\n{\r\n  BUILDING_SIMPLE,\r\n  BUILDING_BLOCKY,\r\n  BUILDING_MODERN,\r\n  BU"
  },
  {
    "path": "Camera.cpp",
    "chars": 10874,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Camera.cpp\r\n\r\n  2009 Shamus Young\r\n"
  },
  {
    "path": "Camera.h",
    "chars": 754,
    "preview": "#ifndef TYPES\r\n#include \"glTypes.h\"\r\n#endif\r\n\r\nGLvector  CameraAngle (void);\r\nvoid      CameraAngleSet (GLvector new_ang"
  },
  {
    "path": "Car.cpp",
    "chars": 8591,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Car.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-"
  },
  {
    "path": "Car.h",
    "chars": 691,
    "preview": "class CCar\r\n{\r\n  GLvector        m_position;\r\n  GLvector        m_drive_position;\r\n  bool            m_ready;\r\n  bool   "
  },
  {
    "path": "Deco.cpp",
    "chars": 8260,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Deco.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n"
  },
  {
    "path": "Deco.h",
    "chars": 810,
    "preview": "#ifndef ENTITY\r\n#include \"entity.h\"\r\n#endif\r\n\r\nclass CDeco : CEntity\r\n{\r\n  GLrgba        _color;\r\n  class CMesh*  _mesh;"
  },
  {
    "path": "Entity.cpp",
    "chars": 10804,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Entity.cpp\r\n\r\n  Copyright (c) 2005 "
  },
  {
    "path": "Entity.h",
    "chars": 844,
    "preview": "#ifndef TYPES\r\n#include \"glTypes.h\"\r\n#endif\r\n\r\n#ifndef ENTITY\r\n\r\n#define ENTITY\r\n\r\nclass CEntity\r\n{\r\nprivate:\r\nprotected"
  },
  {
    "path": "Ini.cpp",
    "chars": 3403,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Ini.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n\r"
  },
  {
    "path": "Ini.h",
    "chars": 335,
    "preview": "int       IniInt (char* entry);\r\nvoid      IniIntSet (char* entry, int val);\r\nfloat     IniFloat (char* entry);\r\nvoid   "
  },
  {
    "path": "Light.cpp",
    "chars": 4591,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Light.cpp\r\n\r\n  2006 Shamus Young\r\n\r"
  },
  {
    "path": "Light.h",
    "chars": 517,
    "preview": "class CLight\r\n{\r\n  GLvector        _position;\r\n  GLrgba          _color;\r\n  int             _size;\r\n  float           _v"
  },
  {
    "path": "Macro.h",
    "chars": 974,
    "preview": "#define LIMIT_INTERVAL(interval)  { static unsigned next_update; if (next_update > GetTickCount ()) return; next_update "
  },
  {
    "path": "Math.cpp",
    "chars": 4560,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Math.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n"
  },
  {
    "path": "Math.h",
    "chars": 538,
    "preview": "float MathAngle (float angle);\r\nfloat MathAngle (float x1, float y1, float x2, float y2);\r\nfloat MathAngleDifference (fl"
  },
  {
    "path": "Mesh.cpp",
    "chars": 4644,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Mesh.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n"
  },
  {
    "path": "Mesh.h",
    "chars": 929,
    "preview": "\r\n#include <vector>\r\n\r\nstruct cube\r\n{\r\n  std::vector<int> index_list;   // probably always .size() == 10...\r\n};\r\n\r\nstruc"
  },
  {
    "path": "PixelCity.dsp",
    "chars": 6504,
    "preview": "# Microsoft Developer Studio Project File - Name=\"PixelCity\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated"
  },
  {
    "path": "Random.cpp",
    "chars": 3020,
    "preview": "/*-----------------------------------------------------------------------------\r\n\t\t\t\t\t\t\t\t\t               r a n d o m\r\n--"
  },
  {
    "path": "Random.h",
    "chars": 165,
    "preview": "#define COIN_FLIP     (RandomVal (2) == 0)\r\n\r\nunsigned long RandomVal (int range);\r\nunsigned long RandomVal (void);\r\nvoi"
  },
  {
    "path": "Render.cpp",
    "chars": 24202,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Render.cpp\r\n\r\n  2009 Shamus Young\r\n"
  },
  {
    "path": "Render.h",
    "chars": 634,
    "preview": "bool  RenderBloom ();\r\nvoid  RenderEffectCycle ();\r\nbool  RenderFlat ();\r\nvoid  RenderFlatToggle ();\r\nfloat RenderFogDis"
  },
  {
    "path": "Sky.cpp",
    "chars": 3510,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Sky.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-"
  },
  {
    "path": "Sky.h",
    "chars": 437,
    "preview": "#define SKY_GRID      21\r\n#define SKY_HALF      (SKY_GRID / 2)\r\n\r\nstruct sky_point\r\n{\r\n  GLrgba        color;\r\n  GLvecto"
  },
  {
    "path": "Texture.cpp",
    "chars": 26850,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Texture.cpp\r\n\r\n  2009 Shamus Young\r"
  },
  {
    "path": "Texture.h",
    "chars": 1340,
    "preview": "#define SEGMENTS_PER_TEXTURE  64\r\n#define ONE_SEGMENT           (1.0f / SEGMENTS_PER_TEXTURE)\r\n#define LANES_PER_TEXTURE"
  },
  {
    "path": "Visible.cpp",
    "chars": 4125,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Visible.cpp\r\n\r\n  2009 Shamus Young\r"
  },
  {
    "path": "Visible.h",
    "chars": 341,
    "preview": "#define GRID_RESOLUTION   32\r\n#define GRID_CELL         (GRID_RESOLUTION / 2)\r\n#define GRID_SIZE         (WORLD_SIZE / G"
  },
  {
    "path": "Win.cpp",
    "chars": 11723,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Win.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-"
  },
  {
    "path": "Win.h",
    "chars": 1758,
    "preview": "//Versioning info\r\n#define APP_TITLE           \"PixelCity\"\r\n#define APP                 \"pixelcity\"\r\n#define VERSION_MAJ"
  },
  {
    "path": "World.cpp",
    "chars": 23228,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  World.cpp\r\n\r\n  2009 Shamus Young\r\n\r"
  },
  {
    "path": "World.h",
    "chars": 416,
    "preview": "\r\nGLrgba    WorldBloomColor ();\r\nchar      WorldCell (int x, int y);\r\nGLrgba    WorldLightColor (unsigned index);\r\nint  "
  },
  {
    "path": "glBbox.cpp",
    "chars": 1953,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  glBbox.cpp\r\n\r\n  2006 Shamus Young\r\n"
  },
  {
    "path": "glMatrix.cpp",
    "chars": 10544,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  glMatrix.cpp\r\n\r\n  2006 Shamus Young"
  },
  {
    "path": "glQuat.cpp",
    "chars": 2536,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  glQuat.cpp\r\n\r\n  2006 Shamus Young\r\n"
  },
  {
    "path": "glRgba.cpp",
    "chars": 9459,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  glRgba.cpp\r\n\r\n  2009 Shamus Young\r\n"
  },
  {
    "path": "glTypes.h",
    "chars": 5114,
    "preview": "#ifndef glTYPES\r\n#define glTYPES\r\n\r\n#define GL_CLAMP_TO_EDGE 0x812F\r\n\r\n#define OPERATORS(type)     \\\r\n  type    operator"
  },
  {
    "path": "glVector2.cpp",
    "chars": 4601,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  Vector2.cpp\r\n\r\n  2006 Shamus Young\r"
  },
  {
    "path": "glVector3.cpp",
    "chars": 5581,
    "preview": "/*-----------------------------------------------------------------------------\r\n\r\n  glVector3.cpp\r\n\r\n  2006 Shamus Youn"
  }
]

About this extraction

This page contains the full source code of the skeeto/pixelcity GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 41 files (235.0 KB), approximately 63.0k tokens, and a symbol index with 231 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!