[
  {
    "path": "Building.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Building.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This module contains the class to construct the buildings.  \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define MAX_VBUFFER         256\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n#include \"glTypes.h\"\r\n\r\n#include \"building.h\"\r\n#include \"deco.h\"\r\n#include \"light.h\"\r\n#include \"mesh.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"random.h\"\r\n#include \"texture.h\"\r\n#include \"world.h\"\r\n#include \"win.h\"\r\n\r\n//This is used by the recursive roof builder to decide what items may be added.\r\nenum\r\n{\r\n  ADDON_NONE,\r\n  ADDON_LOGO,\r\n  ADDON_TRIM,\r\n  ADDON_LIGHTS,\r\n  ADDON_COUNT\r\n};\r\n\r\nstatic GLvector         vector_buffer[MAX_VBUFFER];\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This is the constructor for our building constructor.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCBuilding::CBuilding (int type, int x, int y, int height, int width, int depth, int seed, GLrgba color)\r\n{\r\n\r\n  _x = x;\r\n  _y = y;\r\n  _width = width;\r\n  _depth = depth;\r\n  _height = height;\r\n  _center = glVector ((float)(_x + width / 2), 0.0f, (float)(_y + depth / 2));\r\n  _seed = seed;\r\n  _texture_type = RandomVal ();\r\n  _color = color;\r\n  _color.alpha = 0.1f;\r\n  _have_lights = false;\r\n  _have_logo = false;\r\n  _have_trim = false;\r\n  _roof_tiers = 0;\r\n  //Pick a color for logos & roof lights\r\n  _trim_color = WorldLightColor (seed);\r\n  _mesh = new CMesh; //The main textured mesh for the building\r\n  _mesh_flat = new CMesh; //Flat-color mesh for untextured detail items.\r\n  switch (type) {\r\n  case BUILDING_SIMPLE:\r\n    CreateSimple ();\r\n    break;  \r\n  case BUILDING_MODERN: \r\n    CreateModern (); \r\n    break;\r\n  case BUILDING_TOWER: \r\n    CreateTower (); \r\n    break;\r\n  case BUILDING_BLOCKY:\r\n    CreateBlocky (); \r\n    break;\r\n  }\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCBuilding::~CBuilding ()\r\n{\r\n\r\n  if (_mesh)\r\n    delete _mesh;\r\n  if (_mesh_flat)\r\n    delete _mesh_flat;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nunsigned CBuilding::Texture ()\r\n{\r\n\r\n  return TextureRandomBuilding (_texture_type);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint CBuilding::PolyCount ()\r\n{\r\n\r\n  return _mesh->PolyCount () + _mesh_flat->PolyCount ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::Render ()\r\n{ \r\n\r\n  glColor3fv (&_color.red);\r\n  _mesh->Render ();\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::RenderFlat (bool colored)\r\n{ \r\n\r\n  if (colored)\r\n    glColor3fv (&_color.red);\r\n  _mesh_flat->Render ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::ConstructCube (int left, int right, int front, int back, int bottom, int top)\r\n{\r\n\r\n  GLvertex    p[10];\r\n  float       x1, x2, z1, z2, y1, y2;\r\n  int         i;\r\n  cube        c;\r\n  float       u, v1, v2;\r\n  float       mapping;\r\n  int         base_index;\r\n  int         height;\r\n\r\n  height = top - bottom;\r\n  x1 = (float)left;\r\n  x2 = (float)right;\r\n  y1 = (float)bottom;\r\n  y2 = (float)top;\r\n  z1 = (float)front;\r\n  z2 = (float)back;\r\n  base_index = _mesh->VertexCount ();\r\n\r\n  mapping = (float)SEGMENTS_PER_TEXTURE;\r\n  u = (float)(RandomVal () % SEGMENTS_PER_TEXTURE) / (float)SEGMENTS_PER_TEXTURE;\r\n  v1 = (float)bottom / (float)mapping;\r\n  v2 = (float)top / (float)mapping;\r\n\r\n  p[0].position = glVector (x1, y1, z1);  p[0].uv = glVector (u, v1);\r\n  p[1].position = glVector (x1, y2, z1);  p[1].uv = glVector (u, v2);\r\n  u += (float)_width / mapping;\r\n  p[2].position = glVector (x2, y1, z1);  p[2].uv = glVector (u, v1);\r\n  p[3].position = glVector (x2, y2, z1);  p[3].uv = glVector (u, v2);\r\n  u += (float)_depth / mapping;\r\n  p[4].position = glVector (x2, y1, z2);  p[4].uv = glVector (u, v1);\r\n  p[5].position = glVector (x2, y2, z2);  p[5].uv = glVector (u, v2);\r\n  u += (float)_width / mapping;\r\n  p[6].position = glVector (x1, y1, z2);  p[6].uv = glVector (u, v1);\r\n  p[7].position = glVector (x1, y2, z2);  p[7].uv = glVector (u, v2);\r\n  u += (float)_width / mapping;\r\n  p[8].position = glVector (x1, y1, z1);  p[8].uv = glVector (u, v1);\r\n  p[9].position = glVector (x1, y2, z1);  p[9].uv = glVector (u, v2);\r\n  for (i = 0; i < 10; i++) {\r\n    p[i].uv.x = (p[i].position.x + p[i].position.z) / (float)SEGMENTS_PER_TEXTURE;\r\n    _mesh->VertexAdd (p[i]);\r\n    c.index_list.push_back(base_index + i);\r\n  }\r\n  _mesh->CubeAdd (c);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::ConstructCube (float left, float right, float front, float back, float bottom, float top)\r\n{\r\n\r\n  GLvertex    p[10];\r\n  float       x1, x2, z1, z2, y1, y2;\r\n  int         i;\r\n  cube        c;\r\n  int         base_index;\r\n\r\n  x1 = left;\r\n  x2 = right;\r\n  y1 = bottom;\r\n  y2 = top;\r\n  z1 = front;\r\n  z2 = back;\r\n  base_index = _mesh_flat->VertexCount ();\r\n\r\n  p[0].position = glVector (x1, y1, z1);  p[0].uv = glVector (0.0f, 0.0f);\r\n  p[1].position = glVector (x1, y2, z1);  p[1].uv = glVector (0.0f, 0.0f);\r\n  p[2].position = glVector (x2, y1, z1);  p[2].uv = glVector (0.0f, 0.0f);\r\n  p[3].position = glVector (x2, y2, z1);  p[3].uv = glVector (0.0f, 0.0f);\r\n  p[4].position = glVector (x2, y1, z2);  p[4].uv = glVector (0.0f, 0.0f);\r\n  p[5].position = glVector (x2, y2, z2);  p[5].uv = glVector (0.0f, 0.0f);\r\n  p[6].position = glVector (x1, y1, z2);  p[6].uv = glVector (0.0f, 0.0f);\r\n  p[7].position = glVector (x1, y2, z2);  p[7].uv = glVector (0.0f, 0.0f);\r\n  p[8].position = glVector (x1, y1, z1);  p[8].uv = glVector (0.0f, 0.0f);\r\n  p[9].position = glVector (x1, y2, z1);  p[9].uv = glVector (0.0f, 0.0f);\r\n  for (i = 0; i < 10; i++) {\r\n    p[i].uv.x = (p[i].position.x + p[i].position.z) / (float)SEGMENTS_PER_TEXTURE;\r\n    _mesh_flat->VertexAdd (p[i]);\r\n    c.index_list.push_back(base_index + i);\r\n  }\r\n  _mesh_flat->CubeAdd (c);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This will take the given area and populate it with rooftop stuff like\r\n  air conditioners or light towers.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::ConstructRoof (float left, float right, float front, float back, float bottom)\r\n{\r\n\r\n  int       air_conditioners;\r\n  int       i;\r\n  int       width, depth, height;\r\n  int       face;\r\n  int       addon;\r\n  int       max_tiers;\r\n  float     ac_x;\r\n  float     ac_y;\r\n  float     ac_base;\r\n  float     ac_size;\r\n  float     ac_height;\r\n  float     tower_height;\r\n  float     logo_offset;\r\n  CDeco*    d;\r\n  GLvector2 start, end;\r\n\r\n  _roof_tiers++;\r\n  max_tiers = _height / 10;\r\n  width = (int)(right - left);\r\n  depth = (int)(back - front);\r\n  height = 5 - _roof_tiers;\r\n  logo_offset = 0.2f;\r\n  //See if this building is special and worthy of fancy roof decorations.\r\n  if (bottom > 35.0f)\r\n    addon = RandomVal (ADDON_COUNT);\r\n  //Build the roof slab\r\n  ConstructCube (left, right, front, back, bottom, bottom + (float)height);\r\n  //Consider putting a logo on the roof, if it's tall enough\r\n  if (addon == ADDON_LOGO && !_have_logo) {\r\n    d = new CDeco;\r\n    if (width > depth)\r\n      face = COIN_FLIP ? NORTH : SOUTH;\r\n    else\r\n      face = COIN_FLIP ? EAST : WEST;\r\n    switch (face) {\r\n    case NORTH:\r\n      start = glVector ((float)left, (float)back + logo_offset);\r\n      end = glVector ((float)right, (float)back + logo_offset);\r\n      break;\r\n    case SOUTH:\r\n      start = glVector ((float)right, (float)front - logo_offset);\r\n      end = glVector ((float)left, (float)front - logo_offset);\r\n      break;\r\n    case EAST:\r\n      start = glVector ((float)right + logo_offset, (float)back);\r\n      end = glVector ((float)right + logo_offset, (float)front);\r\n      break;\r\n    case WEST:\r\n    default:\r\n      start = glVector ((float)left - logo_offset, (float)front);\r\n      end = glVector ((float)left - logo_offset, (float)back);\r\n      break;\r\n    }\r\n    d->CreateLogo (start, end, bottom, WorldLogoIndex (), _trim_color);\r\n    _have_logo = true;\r\n  } else if (addon == ADDON_TRIM) {\r\n    d = new CDeco;\r\n    vector_buffer[0] = glVector (left, bottom, back);\r\n    vector_buffer[1] = glVector (left, bottom, front);\r\n    vector_buffer[2] = glVector (right, bottom, front);\r\n    vector_buffer[3] = glVector (right, bottom, back);\r\n    d->CreateLightTrim (vector_buffer, 4, (float)RandomVal (2) + 1.0f, _seed, _trim_color);\r\n  } else if (addon == ADDON_LIGHTS && !_have_lights) {\r\n    new CLight (glVector (left, (float)(bottom + 2), front), _trim_color, 2);\r\n    new CLight (glVector (right, (float)(bottom + 2), front), _trim_color, 2);\r\n    new CLight (glVector (right, (float)(bottom + 2), back), _trim_color, 2);\r\n    new CLight (glVector (left, (float)(bottom + 2), back), _trim_color, 2);\r\n    _have_lights = true;\r\n  }\r\n  bottom += (float)height;\r\n  //If the roof is big enough, consider making another layer \r\n  if (width > 7 && depth > 7 && _roof_tiers < max_tiers) {\r\n    ConstructRoof (left + 1, right - 1, front + 1, back - 1, bottom);\r\n    return;\r\n  }\r\n  //1 air conditioner block for every 15 floors sounds reasonble\r\n  air_conditioners = _height / 15;\r\n  for (i = 0; i < air_conditioners; i++) {\r\n    ac_size = (float)(10 + RandomVal (30)) / 10;\r\n    ac_height = (float)RandomVal (20) / 10 + 1.0f;\r\n    ac_x = left + (float)RandomVal (width);\r\n    ac_y = front + (float)RandomVal (depth);\r\n    //make sure the unit doesn't hang off the right edge of the building\r\n    if (ac_x + ac_size > (float)right)\r\n      ac_x = (float)right - ac_size;\r\n    //make sure the unit doesn't hang off the back edge of the building\r\n    if (ac_y + ac_size > (float)back)\r\n      ac_y = (float)back - ac_size;\r\n    ac_base = (float)bottom;\r\n    //make sure it doesn't hang off the edge\r\n    ConstructCube (ac_x, ac_x + ac_size, ac_y, ac_y + ac_size, ac_base, ac_base + ac_height);\r\n  }\r\n\r\n  if (_height > 45) {\r\n    d = new CDeco;\r\n    tower_height = (float)(12 + RandomVal (8));\r\n    d->CreateRadioTower (glVector ((float)(left + right) / 2.0f, (float)bottom, (float)(front + back) / 2.0f), 15.0f);\r\n  }\r\n  \r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::ConstructSpike (int left, int right, int front, int back, int bottom, int top)\r\n{\r\n\r\n  GLvertex    p;\r\n  fan         f;\r\n  int         i;\r\n  GLvector    center;\r\n\r\n  for (i = 0; i < 5; i++)\r\n    f.index_list.push_back(_mesh_flat->VertexCount () + i);\r\n  f.index_list.push_back(f.index_list[1]);\r\n  p.uv = glVector (0.0f, 0.0f);\r\n  center.x = ((float)left + (float)right) / 2.0f;\r\n  center.z = ((float)front + (float)back) / 2.0f;\r\n  p.position = glVector (center.x, (float)top, center.z);\r\n  _mesh_flat->VertexAdd (p);\r\n \r\n  p.position = glVector ((float)left, (float)bottom, (float)back);\r\n  _mesh_flat->VertexAdd (p);\r\n\r\n  p.position = glVector ((float)right, (float)bottom, (float)back);\r\n  _mesh_flat->VertexAdd (p);\r\n\r\n  p.position = glVector ((float)right, (float)bottom, (float)front);\r\n  _mesh_flat->VertexAdd (p);\r\n  \r\n  p.position = glVector ((float)left, (float)bottom, (float)front);\r\n  _mesh_flat->VertexAdd (p);\r\n  \r\n  _mesh_flat->FanAdd (f);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This builds an outer wall of a building, with blank (windowless) areas\r\n  deliberately left.  It creates a chain of segments that alternate\r\n  between windowed and windowless, and it always makes sure the wall\r\n  is symetrical.  window_groups tells it how many windows to place in a row.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat 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)\r\n{\r\n\r\n  int         x, z;\r\n  int         step_x, step_z;\r\n  int         i;\r\n  quad_strip  qs;\r\n  int         column;\r\n  int         mid;\r\n  int         odd;\r\n  GLvertex    v;\r\n  bool        blank;\r\n  bool        last_blank;\r\n\r\n  qs.index_list.reserve(100);\r\n\r\n  switch (direction) {\r\n  case NORTH:\r\n    step_z = 1; step_x = 0; break;\r\n  case WEST:\r\n    step_z = 0; step_x = -1; break;\r\n  case SOUTH:\r\n    step_z = -1; step_x = 0; break;\r\n  case EAST:\r\n    step_z = 0; step_x = 1; break;\r\n  }\r\n  x = start_x;;\r\n  z = start_z;\r\n  mid = (length / 2) - 1;\r\n  odd = 1 - (length % 2);\r\n  if (length % 2) \r\n    mid++;\r\n  //mid = (length / 2);\r\n  v.uv.x = (float)(x + z) / SEGMENTS_PER_TEXTURE;\r\n  v.uv.x = uv_start;\r\n  blank = false;\r\n  for (i = 0; i <= length; i++) {\r\n    //column counts up to the mid point, then back down, to make it symetrical\r\n    if (i <= mid)\r\n      column = i - odd;\r\n    else \r\n      column = (mid) - (i - (mid));\r\n    last_blank = blank;\r\n    blank = (column % window_groups) > window_groups / 2;\r\n    if (blank_corners && i == 0)\r\n      blank = true;\r\n    if (blank_corners && i == (length - 1))\r\n      blank = true;\r\n    if (last_blank != blank || i == 0 || i == length) {\r\n      v.position = glVector ((float)x, (float)start_y, (float)z);\r\n      v.uv.y = (float)start_y / SEGMENTS_PER_TEXTURE;\r\n      _mesh->VertexAdd (v);\r\n      qs.index_list.push_back(_mesh->VertexCount () - 1);\r\n      v.position.y = (float)(start_y + height);\r\n      v.uv.y = (float)(start_y + height) / SEGMENTS_PER_TEXTURE;;\r\n      _mesh->VertexAdd (v);\r\n      qs.index_list.push_back(_mesh->VertexCount () - 1);\r\n    }\r\n    //if (!blank && i != 0 && i != (length - 1))\r\n    if (!blank && i != length)\r\n      v.uv.x += 1.0f / SEGMENTS_PER_TEXTURE;\r\n    x += step_x;\r\n    z += step_z;\r\n  }\r\n  _mesh->QuadStripAdd (qs);  \r\n  return v.uv.x;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This makes a big chunky building of intersecting cubes.  \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::CreateBlocky ()\r\n{\r\n\r\n  int         min_height;\r\n  int         left, right, front, back;\r\n  int         max_left, max_right, max_front, max_back;\r\n  int         height;\r\n  int         mid_x, mid_z;\r\n  int         half_depth, half_width;\r\n  int         tiers;\r\n  int         max_tiers;\r\n  int         grouping;\r\n  float       lid_height;\r\n  float       uv_start;\r\n  bool        skip;\r\n  bool        blank_corners;\r\n\r\n  //Choose if the corners of the building are to be windowless.\r\n  blank_corners = COIN_FLIP;\r\n  //Choose a random column on our texture;\r\n  uv_start = (float)RandomVal (SEGMENTS_PER_TEXTURE) / SEGMENTS_PER_TEXTURE;\r\n  //Choose how the windows are grouped\r\n  grouping = 2 + RandomVal (4);\r\n  //Choose how tall the lid should be on top of each section\r\n  lid_height = (float)(RandomVal (3) + 1);\r\n  //find the center of the building.\r\n  mid_x = _x + _width / 2;\r\n  mid_z = _y + _depth / 2;\r\n  max_left = max_right = max_front = max_back = 1;\r\n  height = _height;\r\n  min_height = _height / 2;\r\n  min_height = 3;\r\n  half_depth = _depth / 2;\r\n  half_width = _width / 2;\r\n  tiers = 0;\r\n  if (_height > 40)\r\n    max_tiers = 15;\r\n  else if (_height > 30)\r\n    max_tiers = 10;\r\n  else if (_height > 20)\r\n    max_tiers = 5;\r\n  else if (_height > 10)\r\n    max_tiers = 2;\r\n  else\r\n    max_tiers = 1;\r\n  //We begin at the top of the building, and work our way down.\r\n  //Viewed from above, the sections of the building are randomly sized\r\n  //rectangles that ALWAYS include the center of the building somewhere within \r\n  //their area.  \r\n  while (1) {\r\n    if (height < min_height)\r\n      break;\r\n    if (tiers >= max_tiers)\r\n      break;\r\n    //pick new locationsfor our four outer walls\r\n    left = (RandomVal () % half_width) + 1;\r\n    right = (RandomVal () % half_width) + 1;\r\n    front = (RandomVal () % half_depth) + 1;\r\n    back = (RandomVal () % half_depth) + 1;\r\n    skip = false;\r\n    //At least ONE of the walls must reach out beyond a previous maximum.\r\n    //Otherwise, this tier would be completely hidden within a previous one.\r\n    if (left <= max_left && right <= max_right && front <= max_front && back <= max_back) \r\n      skip = true;\r\n    //If any of the four walls is in the same position as the previous max,then\r\n    //skip this tier, or else the two walls will end up z-fightng.\r\n    if (left == max_left || right == max_right || front == max_front || back == max_back) \r\n      skip = true;\r\n    if (!skip) {\r\n      //if this is the top, then put some lights up here\r\n      max_left = MAX (left, max_left);\r\n      max_right = MAX (right, max_right);\r\n      max_front = MAX (front, max_front);\r\n      max_back = MAX (back, max_back);\r\n      //Now build the four walls of this part\r\n      uv_start = ConstructWall (mid_x - left, 0, mid_z + back, SOUTH, front + back, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n      uv_start = ConstructWall (mid_x - left, 0, mid_z - front, EAST, right + left, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n      uv_start = ConstructWall (mid_x + right, 0, mid_z - front, NORTH, front + back, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n      uv_start = ConstructWall (mid_x + right, 0, mid_z + back, WEST, right + left, height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n      if (!tiers)\r\n        ConstructRoof ((float)(mid_x - left), (float)(mid_x + right), (float)(mid_z - front), (float)(mid_z + back), (float)height);\r\n      else //add a flat-color lid onto this section\r\n        ConstructCube ((float)(mid_x - left), (float)(mid_x + right), (float)(mid_z - front), (float)(mid_z + back), (float)height, (float)height + lid_height);\r\n      height -= (RandomVal () % 10) + 1;\r\n      tiers++;\r\n    }\r\n    height--;\r\n  }\r\n  ConstructCube (mid_x - half_width, mid_x + half_width, mid_z - half_depth, mid_z + half_depth, 0, 2);\r\n  _mesh->Compile ();\r\n  _mesh_flat->Compile ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  A single-cube building.  Good for low-rise buildings and stuff that will be \r\n  far from the camera;\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::CreateSimple ()\r\n{\r\n\r\n  GLvertex    p;\r\n  float       x1, x2, z1, z2, y1, y2;\r\n  quad_strip  qs;\r\n  float       u, v1, v2;\r\n  float       cap_height;\r\n  float       ledge;\r\n\r\n  for(int i=0; i<10; i++)\r\n    qs.index_list.push_back(i);\r\n\r\n  //How tall the flat-color roof is\r\n  cap_height = (float)(1 + RandomVal (4));\r\n  //how much the ledge sticks out\r\n  ledge = (float)RandomVal (10) / 30.0f;\r\n\r\n  x1 = (float)_x;\r\n  x2 = (float)(_x + _width);\r\n  y1 = (float)0.0f;\r\n  y2 = (float)_height;\r\n  z2 = (float)_y;\r\n  z1 = (float)(_y + _depth);\r\n\r\n  u = (float)(RandomVal (SEGMENTS_PER_TEXTURE)) / SEGMENTS_PER_TEXTURE;\r\n  v1 = (float)(RandomVal (SEGMENTS_PER_TEXTURE)) / SEGMENTS_PER_TEXTURE;\r\n  v2 = v1 + (float)_height * ONE_SEGMENT;\r\n\r\n  p.position = glVector (x1, y1, z1);  p.uv = glVector (u, v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x1, y2, z1);  p.uv = glVector (u, v2);\r\n  _mesh->VertexAdd (p);\r\n  u += (float)_depth / SEGMENTS_PER_TEXTURE;\r\n\r\n  p.position = glVector (x1, y1, z2);  p.uv = glVector (u, v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x1, y2, z2);  p.uv = glVector (u, v2);\r\n  _mesh->VertexAdd (p);\r\n  u += (float)_width / SEGMENTS_PER_TEXTURE;\r\n  \r\n  p.position = glVector (x2, y1, z2);  p.uv = glVector (u, v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x2, y2, z2);  p.uv = glVector (u, v2);\r\n  _mesh->VertexAdd (p);\r\n  u += (float)_depth / SEGMENTS_PER_TEXTURE;\r\n\r\n  p.position = glVector (x2, y1, z1);  p.uv = glVector (u, v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x2, y2, z1);  p.uv = glVector (u, v2);\r\n  _mesh->VertexAdd (p);\r\n  u += (float)_depth / SEGMENTS_PER_TEXTURE;\r\n\r\n  p.position = glVector (x1, y1, z1);  p.uv = glVector (u, v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x1, y2, z1);  p.uv = glVector (u, v2);\r\n  _mesh->VertexAdd (p);\r\n\r\n  _mesh->QuadStripAdd (qs);\r\n  ConstructCube (x1 - ledge, x2 + ledge, z2 - ledge, z1 + ledge, (float)_height, (float)_height + cap_height);\r\n  _mesh->Compile ();\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This makes a deformed cylinder building.  \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::CreateModern ()\r\n{\r\n\r\n  GLvertex    p;\r\n  GLvector    center;\r\n  GLvector    pos;\r\n  GLvector2   radius;\r\n  GLvector2   start, end;\r\n  int         angle;\r\n  int         windows;\r\n  int         cap_height;\r\n  int         half_depth, half_width;\r\n  float       dist;\r\n  float       length;\r\n  quad_strip  qs;\r\n  fan         f;\r\n  int         points;\r\n  int         skip_interval;\r\n  int         skip_counter;\r\n  int         skip_delta;\r\n  int         i;\r\n  bool        logo_done;\r\n  bool        do_trim;\r\n  CDeco*      d;\r\n\r\n  logo_done = false;\r\n  //How tall the windowless section on top will be.\r\n  cap_height = 1 + RandomVal (5);\r\n  //How many 10-degree segments to build before the next skip.\r\n  skip_interval = 1 + RandomVal (8);\r\n  //When a skip happens, how many degrees should be skipped\r\n  skip_delta = (1 + RandomVal (2)) * 30; //30 60 or 90\r\n  //See if this is eligible for fancy lighting trim on top\r\n  if (_height > 48 && RandomVal (3) == 0)\r\n    do_trim = true;\r\n  else\r\n    do_trim = false;\r\n  //Get the center and radius of the circle\r\n  half_depth = _depth / 2;\r\n  half_width = _width / 2;\r\n  center = glVector ((float)(_x + half_width), 0.0f, (float)(_y + half_depth));\r\n  radius = glVector ((float)half_width, (float)half_depth);\r\n  dist = 0;\r\n  windows = 0;\r\n  p.uv.x = 0.0f;\r\n  points = 0;\r\n  skip_counter = 0;\r\n  for (angle = 0; angle <= 360; angle += 10) {\r\n    if (skip_counter >= skip_interval && (angle + skip_delta < 360)) {\r\n      angle += skip_delta;\r\n      skip_counter = 0;\r\n    }\r\n    pos.x = center.x - sinf ((float)angle * DEGREES_TO_RADIANS) * radius.x;\r\n    pos.z = center.z + cosf ((float)angle * DEGREES_TO_RADIANS) * radius.y;\r\n    if (angle > 0 && skip_counter == 0) {\r\n      length = MathDistance (p.position.x, p.position.z, pos.x, pos.z);\r\n      windows += (int)length;\r\n      if (length > 10 && !logo_done) {\r\n        logo_done = true;\r\n        start = glVector (pos.x, pos.z);\r\n        end = glVector (p.position.x, p.position.z);\r\n        d = new CDeco;\r\n        d->CreateLogo (start, end, (float)_height, WorldLogoIndex (), RANDOM_COLOR);\r\n      }\r\n    } else if (skip_counter != 1)\r\n      windows++;\r\n    p.position = pos;\r\n    p.uv.x = (float)windows / (float)SEGMENTS_PER_TEXTURE;\r\n    p.uv.y = 0.0f;\r\n    p.position.y = 0.0f;\r\n    _mesh->VertexAdd (p);\r\n    p.position.y = (float)_height;\r\n    p.uv.y = (float)_height / (float)SEGMENTS_PER_TEXTURE;\r\n    _mesh->VertexAdd (p);\r\n    _mesh_flat->VertexAdd (p);\r\n    p.position.y += (float)cap_height;\r\n    _mesh_flat->VertexAdd (p);\r\n    vector_buffer[points / 2] = p.position;\r\n    vector_buffer[points / 2].y = (float)_height + cap_height / 4;\r\n    points += 2;\r\n    skip_counter++;\r\n  }\r\n  //if this is a big building and it didn't get a logo, consider giving it a light strip\r\n  if (!logo_done && do_trim) {\r\n    d = new CDeco;\r\n    d->CreateLightTrim (vector_buffer, (points / 2) - 2, (float)cap_height / 2, _seed, RANDOM_COLOR);\r\n  }\r\n  qs.index_list.reserve(points);   \r\n  //Add the outer walls\r\n  for (i = 0; i < points; i++)\r\n    qs.index_list.push_back(i);\r\n  _mesh->QuadStripAdd (qs);\r\n  _mesh_flat->QuadStripAdd (qs);\r\n  //add the fan to cap the top of the buildings\r\n  f.index_list.push_back(points);\r\n  for (i = 0; i < points / 2; i++)\r\n    f.index_list.push_back(points - (1 + i * 2));\r\n  p.position.x = _center.x;\r\n  p.position.z = _center.z;\r\n  _mesh_flat->VertexAdd (p);\r\n  _mesh_flat->FanAdd (f);\r\n  radius /= 2.0f;\r\n  //ConstructRoof ((int)(_center.x - radius), (int)(_center.x + radius), (int)(_center.z - radius), (int)(_center.z + radius), _height + cap_height);\r\n  _mesh->Compile ();\r\n  _mesh_flat->Compile ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CBuilding::CreateTower ()\r\n{\r\n\r\n  int         left, right, front, back, bottom;\r\n  int         section_height, section_width, section_depth;\r\n  int         remaining_height;\r\n  int         ledge_height;\r\n  int         tier_fraction;\r\n  int         grouping;\r\n  int         foundation;\r\n  int         narrowing_interval;\r\n  int         tiers;\r\n  float       ledge;\r\n  float       uv_start;\r\n  bool        blank_corners;\r\n  bool        roof_spike;\r\n  bool        tower;\r\n\r\n  //How much ledges protrude from the building\r\n  ledge = (float)RandomVal (3) * 0.25f;\r\n  //How tall the ledges are, in stories\r\n  ledge_height = RandomVal (4) + 1;\r\n  //How the windows are grouped\r\n  grouping = RandomVal (3) + 2;\r\n  //if the corners of the building have no windows\r\n  blank_corners = RandomVal (4) > 0;\r\n  //if the roof is pointed or has infrastructure on it\r\n  roof_spike = RandomVal (3) == 0;\r\n  //What fraction of the remaining height should be given to each tier\r\n  tier_fraction = 2 + RandomVal (4);\r\n  //How often (in tiers) does the building get narrorwer?\r\n  narrowing_interval = 1 + RandomVal (10);\r\n  //The height of the windowsless slab at the bottom\r\n  foundation = 2 + RandomVal (3);\r\n  //The odds that we'll have a big fancy spikey top\r\n  tower = RandomVal (5) != 0 && _height > 40;\r\n  //set our initial parameters\r\n  left = _x; \r\n  right = _x + _width;\r\n  front = _y;\r\n  back = _y + _depth;\r\n  bottom = 0;\r\n  tiers = 0;\r\n  //build the foundations.\r\n  ConstructCube ((float)left - ledge, (float)right + ledge, (float)front - ledge, (float)back + ledge, (float)bottom, (float)foundation);\r\n  bottom += foundation;\r\n  //now add tiers until we reach the top\r\n  while (1) {\r\n    remaining_height = _height - bottom;\r\n    section_depth = back - front;\r\n    section_width = right - left;\r\n    section_height = MAX (remaining_height / tier_fraction, 2);\r\n    if (remaining_height < 10)\r\n      section_height = remaining_height;\r\n    //Build the four walls\r\n    uv_start = (float)RandomVal (SEGMENTS_PER_TEXTURE) / SEGMENTS_PER_TEXTURE;\r\n    uv_start = ConstructWall (left, bottom, back, SOUTH, section_depth, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n    uv_start = ConstructWall (left, bottom, front, EAST, section_width, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n    uv_start = ConstructWall (right, bottom, front, NORTH, section_depth, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n    uv_start = ConstructWall (right, bottom, back, WEST, section_width, section_height, grouping, uv_start, blank_corners) - ONE_SEGMENT;\r\n    bottom += section_height;\r\n    //Build the slab / ledges to cap this section.\r\n    if (bottom + ledge_height > _height)\r\n      break;\r\n    ConstructCube ((float)left - ledge, (float)right + ledge, (float)front - ledge, (float)back + ledge, (float)bottom, (float)(bottom + ledge_height));\r\n    bottom += ledge_height;\r\n    if (bottom > _height)\r\n      break;\r\n    tiers++;\r\n    if ((tiers % narrowing_interval) == 0) {\r\n      if (section_width > 7) {\r\n        left+=1;\r\n        right-=1;\r\n      }\r\n      if (section_depth > 7) {\r\n        front+=1;\r\n        back-=1;\r\n      }\r\n    }\r\n  }\r\n  ConstructRoof ((float)left, (float)right, (float)front, (float)back, (float)bottom);\r\n  _mesh->Compile ();\r\n  _mesh_flat->Compile ();\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Building.h",
    "content": "#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  BUILDING_TOWER\r\n};\r\n\r\nclass CBuilding : public CEntity\r\n{\r\nprivate:\r\n\r\n  int                     _x;\r\n  int                     _y;\r\n  int                     _width;\r\n  int                     _depth;\r\n  int                     _height;\r\n  int                     _texture_type;\r\n  int                     _seed;\r\n  int                     _roof_tiers;\r\n  GLrgba                  _color;\r\n  GLrgba                  _trim_color;\r\n  class CMesh*            _mesh;\r\n  class CMesh*            _mesh_flat;\r\n  bool                    _have_lights;\r\n  bool                    _have_trim;\r\n  bool                    _have_logo;\r\n\r\n\r\n  void                    CreateSimple ();\r\n  void                    CreateBlocky ();\r\n  void                    CreateModern ();\r\n  void                    CreateTower ();\r\n  \r\n  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);\r\n  void                    ConstructSpike (int left, int right, int front, int back, int bottom, int top);\r\n  void                    ConstructCube (int left, int right, int front, int back, int bottom, int top);\r\n  void                    ConstructCube (float left, float right, float front, float back, float bottom, float top);\r\n  void                    ConstructRoof (float left, float right, float front, float back, float bottom);\r\n\r\npublic:\r\n                          CBuilding (int type, int x, int y, int height, int width, int depth, int seed, GLrgba color);\r\n                          ~CBuilding ();\r\n  void                    Render (void);\r\n  int                     PolyCount ();\r\n  void                    RenderFlat (bool colored);\r\n  unsigned                Texture ();\r\n\r\n};\r\n"
  },
  {
    "path": "Camera.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Camera.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This tracks the position and oritentation of the camera. In screensaver \r\n  mode, it moves the camera around the world in order to create dramatic \r\n  views of the hot zone.  \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define EYE_HEIGHT              2.0f\r\n#define MAX_PITCH               85\r\n#define FLYCAM_CIRCUT           60000\r\n#define FLYCAM_CIRCUT_HALF      (FLYCAM_CIRCUT / 2)\r\n#define FLYCAM_LEG              (FLYCAM_CIRCUT / 4)\r\n#define ONE_SECOND              1000\r\n#define CAMERA_CHANGE_INTERVAL  15\r\n#define CAMERA_CYCLE_LENGTH     (CAMERA_MODES*CAMERA_CHANGE_INTERVAL)\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <time.h>\r\n\r\n#include \"glTypes.h\"\r\n#include \"ini.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"world.h\"\r\n#include \"win.h\"\r\n\r\n\r\nenum\r\n{\r\n  CAMERA_FLYCAM1,\r\n  CAMERA_ORBIT_INWARD,\r\n  CAMERA_ORBIT_OUTWARD,\r\n  CAMERA_ORBIT_ELLIPTICAL,\r\n  CAMERA_FLYCAM2,\r\n  CAMERA_SPEED,\r\n  CAMERA_SPIN,\r\n  CAMERA_FLYCAM3,\r\n  CAMERA_MODES\r\n};\r\n\r\nstatic GLvector     angle;\r\nstatic GLvector     position;\r\nstatic GLvector     auto_angle;\r\nstatic GLvector     auto_position;\r\nstatic float        distance;\r\nstatic GLvector     movement;\r\nstatic bool         cam_auto;\r\nstatic float        tracker;\r\nstatic unsigned     last_update;\r\nstatic int          camera_behavior;\r\nstatic unsigned     last_move;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic GLvector flycam_position (unsigned t)\r\n{\r\n\r\n  unsigned    leg;\r\n  float       delta;\r\n  GLvector    start, end;\r\n  GLbbox      hot_zone;\r\n\r\n  hot_zone = WorldHotZone ();\r\n  t %= FLYCAM_CIRCUT; \r\n  leg = t / FLYCAM_LEG;\r\n  delta = (float)(t % FLYCAM_LEG) / FLYCAM_LEG;\r\n  switch (leg) {\r\n  case 0:\r\n    start = glVector (hot_zone.min.x, 25.0f, hot_zone.min.z);\r\n    end = glVector (hot_zone.min.x, 60.0f, hot_zone.max.z);\r\n    break;\r\n  case 1:\r\n    start = glVector (hot_zone.min.x, 60.0f, hot_zone.max.z);\r\n    end = glVector (hot_zone.max.x, 25.0f, hot_zone.max.z);\r\n    break;\r\n  case 2:\r\n    start = glVector (hot_zone.max.x, 25.0f, hot_zone.max.z);\r\n    end = glVector (hot_zone.max.x, 60.0f, hot_zone.min.z);\r\n    break;\r\n  case 3:\r\n    start = glVector (hot_zone.max.x, 60.0f, hot_zone.min.z);\r\n    end = glVector (hot_zone.min.x, 25.0f, hot_zone.min.z);\r\n    break;\r\n  }\r\n  delta = MathScalarCurve (delta);\r\n  return glVectorInterpolate (start, end, delta);\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void do_auto_cam ()\r\n{\r\n\r\n  float     dist;\r\n  unsigned  t;\r\n  unsigned  elapsed;\r\n  unsigned  now;\r\n  int       behavior; \r\n  GLvector  target;\r\n\r\n  now = GetTickCount ();\r\n  elapsed = now - last_update;\r\n  elapsed = MIN (elapsed, 50); //limit to 1/20th second worth of time\r\n  if (elapsed == 0)\r\n    return;\r\n  last_update = now;\r\n  t = time (NULL) % CAMERA_CYCLE_LENGTH;\r\n#if SCREENSAVER\r\n  behavior = t / CAMERA_CHANGE_INTERVAL;\r\n#else\r\n  behavior = camera_behavior;\r\n#endif\r\n  tracker += (float)elapsed / 300.0f;\r\n  //behavior = CAMERA_FLYCAM1; \r\n  switch (behavior) {\r\n  case CAMERA_ORBIT_INWARD:\r\n    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 150.0f;\r\n    auto_position.y = 60.0f;\r\n    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 150.0f;\r\n    target = glVector (WORLD_HALF, 40.0f, WORLD_HALF);\r\n    break;\r\n  case CAMERA_ORBIT_OUTWARD:\r\n    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 250.0f;\r\n    auto_position.y = 60.0f;\r\n    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 250.0f;\r\n    target = glVector (WORLD_HALF, 30.0f, WORLD_HALF);\r\n    break;\r\n  case CAMERA_ORBIT_ELLIPTICAL:\r\n    dist = 150.0f + sinf (tracker * DEGREES_TO_RADIANS / 1.1f) * 50;\r\n    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * dist;\r\n    auto_position.y = 60.0f;\r\n    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * dist;\r\n    target = glVector (WORLD_HALF, 50.0f, WORLD_HALF);\r\n    break;\r\n  case CAMERA_FLYCAM1:\r\n  case CAMERA_FLYCAM2:\r\n  case CAMERA_FLYCAM3:\r\n    auto_position = (flycam_position (now) + flycam_position (now + 4000)) / 2.0f;\r\n    target = flycam_position (now + FLYCAM_CIRCUT_HALF - ONE_SECOND * 3);\r\n    break;\r\n  case CAMERA_SPEED:\r\n    auto_position = (flycam_position (now) + flycam_position (now + 500)) / 2.0f;\r\n    target = flycam_position (now + ONE_SECOND * 5);\r\n    auto_position.y /= 2;\r\n    target.y /= 2;\r\n    break;\r\n  case CAMERA_SPIN:\r\n  default:  \r\n    target.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 300.0f;\r\n    target.y = 30.0f;\r\n    target.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 300.0f;\r\n    auto_position.x = WORLD_HALF + sinf (tracker * DEGREES_TO_RADIANS) * 50.0f;\r\n    auto_position.y = 60.0f;\r\n    auto_position.z = WORLD_HALF + cosf (tracker * DEGREES_TO_RADIANS) * 50.0f;\r\n  }\r\n  dist = MathDistance (auto_position.x, auto_position.z, target.x, target.z);\r\n  auto_angle.y = MathAngle (-MathAngle (auto_position.x, auto_position.z, target.x, target.z));\r\n  auto_angle.x = 90.0f + MathAngle (0, auto_position.y, dist, target.y);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraAutoToggle ()\r\n{\r\n\r\n  cam_auto = !cam_auto;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraNextBehavior ()\r\n{\r\n\r\n  camera_behavior++;\r\n  camera_behavior %= CAMERA_MODES;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraYaw (float delta)\r\n{\r\n\r\n  angle.y -= delta;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraPitch (float delta)\r\n{\r\n\r\n  angle.x -= delta;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraPan (float delta)\r\n{\r\n\r\n  float           move_x, move_y;\r\n\r\n  move_x = (float)sin (-angle.y * DEGREES_TO_RADIANS) / 10.0f;\r\n  move_y = (float)cos (-angle.y * DEGREES_TO_RADIANS) / 10.0f;\r\n  position.x -= move_y * delta;\r\n  position.z -= -move_x * delta;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraForward (float delta)\r\n{\r\n\r\n  float           move_x, move_y;\r\n\r\n  move_y = (float)sin (-angle.y * DEGREES_TO_RADIANS) / 10.0f;\r\n  move_x = (float)cos (-angle.y * DEGREES_TO_RADIANS) / 10.0f;\r\n  position.x -= move_y * delta;\r\n  position.z -= move_x * delta;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraVertical (float val)\r\n{\r\n\r\n  movement.y += val;\r\n  last_move = GetTickCount ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraLateral (float val)\r\n{\r\n\r\n  movement.x += val;\r\n  last_move = GetTickCount ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraMedial (float val)\r\n{\r\n\r\n  movement.z += val;\r\n  last_move = GetTickCount ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector CameraPosition (void)\t\t\r\n{\r\n \r\n  if (cam_auto)\r\n    return auto_position;\r\n  return position;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraReset ()\t\t\r\n{\r\n\r\n  position.y = 50.0f;\r\n  position.x = WORLD_HALF;\r\n  position.z = WORLD_HALF;\r\n  angle.x = 0.0f;\r\n  angle.y = 0.0f;\r\n  angle.z = 0.0f;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraPositionSet (GLvector new_pos)\t\t\r\n{\r\n\r\n  position = new_pos;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector CameraAngle (void)\t\t\r\n{\r\n\r\n  if (cam_auto)\r\n    return auto_angle;\r\n  return angle;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraAngleSet (GLvector new_angle)\t\t\r\n{\r\n\r\n  angle = new_angle;\r\n  angle.x = CLAMP (angle.x, -80.0f, 80.0f);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraInit (void)\t\t\r\n{\r\n\r\n  angle = IniVector (\"CameraAngle\");\r\n  position = IniVector (\"CameraPosition\");\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraUpdate (void)\t\t\r\n{\r\n\r\n  CameraPan (movement.x);\r\n  CameraForward (movement.z);\r\n  position.y += movement.y / 10.0f;\r\n  if (GetTickCount () - last_move > 1000)\r\n    movement *= 0.9f;\r\n  else\r\n    movement *= 0.99f;\r\n  if (SCREENSAVER)\r\n    cam_auto = true;\r\n  if (cam_auto) \r\n    do_auto_cam ();\r\n  if (angle.y < 0.0f) \r\n    angle.y = 360.0f - (float)fmod (fabs (angle.y), 360.0f);\r\n  angle.y = (float)fmod (angle.y, 360.0f);\r\n  angle.x = CLAMP (angle.x, -MAX_PITCH, MAX_PITCH);\r\n \r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CameraTerm (void)\t\t\r\n{\r\n\r\n  //just store our most recent position in the ini\r\n  IniVectorSet (\"CameraAngle\", angle);\r\n  IniVectorSet (\"CameraPosition\", position);\r\n \r\n}\r\n"
  },
  {
    "path": "Camera.h",
    "content": "#ifndef TYPES\r\n#include \"glTypes.h\"\r\n#endif\r\n\r\nGLvector  CameraAngle (void);\r\nvoid      CameraAngleSet (GLvector new_angle);\r\nvoid      CameraAutoToggle ();\r\nfloat     CameraDistance (void);\r\nvoid      CameraDistanceSet (float new_distance);\r\nvoid      CameraInit (void);\r\nvoid      CameraNextBehavior (void);\r\nGLvector  CameraPosition (void);\r\nvoid      CameraPositionSet (GLvector new_pos);\r\nvoid      CameraReset ();\r\nvoid      CameraUpdate (void);\t\r\nvoid      CameraTerm (void);\r\n\r\nvoid      CameraForward (float delta);\r\nvoid      CameraPan (float delta_x);\r\nvoid      CameraPitch (float delta_y);\r\nvoid      CameraYaw (float delta_x);\r\nvoid      CameraVertical (float val);\r\nvoid      CameraLateral (float val);\r\nvoid      CameraMedial (float val);"
  },
  {
    "path": "Car.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Car.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This creates the little two-triangle cars and moves them around the map.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define DEAD_ZONE       200\r\n#define STUCK_TIME      230\r\n#define UPDATE_INTERVAL 50 //milliseconds\r\n#define MOVEMENT_SPEED  0.61f\r\n#define CAR_SIZE        3.0f\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n#include <gl\\glu.h>\r\n#include <gl\\glaux.h>\r\n#include \"glTypes.h\"\r\n\r\n#include \"building.h\"\r\n#include \"car.h\"\r\n#include \"camera.h\"\r\n#include \"mesh.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"texture.h\"\r\n#include \"world.h\"\r\n#include \"visible.h\"\r\n#include \"win.h\"\r\n\r\nstatic GLvector           direction[] = \r\n{\r\n  0.0f, 0.0f, -1.0f,\r\n  1.0f, 0.0f,  0.0f,\r\n  0.0f, 0.0f,  1.0f,\r\n -1.0f, 0.0f,  0.0f,\r\n};\r\n\r\nstatic int                dangles[] = { 0, 90, 180, 270};\r\n\r\nstatic GLvector2          angles[360];\r\nstatic bool               angles_done;\r\nstatic unsigned char      carmap[WORLD_SIZE][WORLD_SIZE];\r\nstatic CCar*              head;\r\nstatic unsigned           next_update;\r\nstatic int                count;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint CarCount ()\r\n{\r\n\r\n  return count;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CarClear ()\r\n{\r\n\r\n  CCar*       c;\r\n\r\n  for (c = head; c; c = c->m_next)\r\n    c->Park ();\r\n  ZeroMemory (carmap, sizeof (carmap));\r\n  count = 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CarRender ()\r\n{\r\n\r\n  CCar*       c;\r\n\r\n  if (!angles_done) {\r\n    for (int i = 0 ;i < 360; i++) {\r\n      angles[i].x = cosf ((float)i * DEGREES_TO_RADIANS) * CAR_SIZE;\r\n      angles[i].y = sinf ((float)i * DEGREES_TO_RADIANS) * CAR_SIZE;\r\n    }\r\n  }\r\n  glDepthMask (false);\r\n  glEnable (GL_BLEND);\r\n  glDisable (GL_CULL_FACE);\r\n  glBlendFunc (GL_ONE, GL_ONE);\r\n  glBindTexture (GL_TEXTURE_2D, 0);\r\n  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_HEADLIGHT));\r\n  for (c = head; c; c = c->m_next)\r\n    c->Render ();\r\n  glDepthMask (true);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CarUpdate ()\r\n{\r\n\r\n  CCar*       c;\r\n  unsigned    now;\r\n\r\n  if (!TextureReady () || !EntityReady ())\r\n    return;\r\n  now = GetTickCount ();\r\n  if (next_update > now)\r\n    return;\r\n  next_update = now + UPDATE_INTERVAL;\r\n  for (c = head; c; c = c->m_next)\r\n    c->Update ();\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCCar::CCar ()\r\n{\r\n\r\n  m_ready = false;\r\n  m_next = head;\r\n  head = this;\r\n  count++;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool CCar::TestPosition (int row, int col)\r\n{\r\n\r\n  //test the given position and see if it's already occupied\r\n  if (carmap[row][col])\r\n    return false;\r\n  //now make sure that the lane is going the right direction\r\n  if (WorldCell (row, col) != WorldCell (m_row, m_col))\r\n    return false;\r\n  return true;\r\n\r\n}\r\n \r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CCar::Update (void)\r\n{\r\n\r\n  int       new_row, new_col;\r\n  GLvector  old_pos;    \r\n  GLvector  camera;\r\n\r\n  //If the car isn't ready, place it on the map and get it moving\r\n  camera = CameraPosition ();\r\n  if (!m_ready) {\r\n    //if the car isn't ready, we need to place it somewhere on the map\r\n    m_row = DEAD_ZONE + RandomVal (WORLD_SIZE - DEAD_ZONE * 2);\r\n    m_col = DEAD_ZONE + RandomVal (WORLD_SIZE - DEAD_ZONE * 2);\r\n    //if there is already a car here, forget it.  \r\n    if (carmap[m_row][m_col] > 0)\r\n      return;\r\n    //if this spot is not a road, forget it\r\n    if (!(WorldCell (m_row, m_col) & CLAIM_ROAD)) \r\n      return;\r\n    if (!Visible (glVector ((float)m_row, 0.0f, (float)m_col)))\r\n      return;\r\n    //good spot. place the car\r\n    m_position = glVector ((float)m_row, 0.1f, (float)m_col);\r\n    m_drive_position = m_position;\r\n    m_ready = true;\r\n    if (WorldCell (m_row, m_col) & MAP_ROAD_NORTH) \r\n      m_direction = NORTH;\r\n    if (WorldCell (m_row, m_col) & MAP_ROAD_EAST) \r\n      m_direction = EAST;\r\n    if (WorldCell (m_row, m_col) & MAP_ROAD_SOUTH) \r\n      m_direction = SOUTH;\r\n    if (WorldCell (m_row, m_col) & MAP_ROAD_WEST) \r\n      m_direction = WEST;\r\n    m_drive_angle = dangles[m_direction];\r\n    m_max_speed = (float)(4 + RandomVal (6)) / 10.0f;\r\n    m_speed = 0.0f;\r\n    m_change = 3;\r\n    m_stuck = 0;\r\n    carmap[m_row][m_col]++;\r\n  }\r\n  //take the car off the map and move it\r\n  carmap[m_row][m_col]--;\r\n  old_pos = m_position;\r\n  m_speed += m_max_speed * 0.05f;\r\n  m_speed = MIN (m_speed, m_max_speed);\r\n  m_position += direction[m_direction] * MOVEMENT_SPEED * m_speed;\r\n  //If the car has moved out of view, there's no need to keep simulating it. \r\n  if (!Visible (glVector ((float)m_row, 0.0f, (float)m_col))) \r\n    m_ready = false;\r\n  //if the car is far away, remove it.  We use manhattan units because buildings almost always\r\n  //block views of cars on the diagonal.\r\n  if (fabs (camera.x - m_position.x) + fabs (camera.z - m_position.z) > RenderFogDistance ())\r\n    m_ready = false;\r\n  //if the car gets too close to the edge of the map, take it out of play\r\n  if (m_position.x < DEAD_ZONE || m_position.x > (WORLD_SIZE - DEAD_ZONE))\r\n    m_ready = false;\r\n  if (m_position.z < DEAD_ZONE || m_position.z > (WORLD_SIZE - DEAD_ZONE))\r\n    m_ready = false;\r\n  if (m_stuck >= STUCK_TIME)\r\n    m_ready = false;\r\n  if (!m_ready)\r\n    return;\r\n  //Check the new position and make sure its not in another car\r\n  new_row = (int)m_position.x;\r\n  new_col = (int)m_position.z;\r\n  if (new_row != m_row || new_col != m_col) {\r\n    //see if the new position places us on top of another car\r\n    if (carmap[new_row][new_col]) {\r\n      m_position = old_pos;\r\n      m_speed = 0.0f;\r\n      m_stuck++;\r\n    } else {\r\n      //look at the new position and decide if we're heading towards or away from the camera\r\n      m_row = new_row;\r\n      m_col = new_col;\r\n      m_change--;\r\n      m_stuck = 0;\r\n      if (m_direction == NORTH)\r\n        m_front = camera.z < m_position.z;\r\n      else if (m_direction == SOUTH)\r\n        m_front = camera.z > m_position.z;\r\n      else if (m_direction == EAST)\r\n        m_front = camera.x > m_position.x;\r\n      else \r\n        m_front = camera.x < m_position.x;\r\n    }\r\n  }\r\n  m_drive_position = (m_drive_position + m_position) / 2.0f;\r\n  //place the car back on the map\r\n  carmap[m_row][m_col]++;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CCar::Render ()\r\n{\r\n\r\n  GLvector  pos;\r\n  int       angle;\r\n  int       turn;\r\n  float     top;\r\n\r\n  if (!m_ready)\r\n    return;\r\n  if (!Visible (m_drive_position))\r\n    return;\r\n  if (m_front) {\r\n    glColor3f (1, 1, 0.8f);\r\n    top = CAR_SIZE;\r\n  } else {\r\n    glColor3f (0.5, 0.2f, 0);\r\n    top = 0.0f;\r\n  }\r\n\r\n  glBegin (GL_QUADS);\r\n\r\n  angle = dangles[m_direction];\r\n  pos = m_drive_position;// \r\n  angle = 360 - (int)MathAngle (m_position.x, m_position.z, pos.x, pos.z);\r\n  angle %= 360;\r\n  turn = (int)MathAngleDifference ((float)m_drive_angle, (float)angle);\r\n  m_drive_angle += SIGN (turn);\r\n  pos += glVector (0.5f, 0.0f, 0.5f);\r\n  \r\n  glTexCoord2f (0, 0);   \r\n  glVertex3f (pos.x + angles[angle].x, -CAR_SIZE, pos.z + angles[angle].y);\r\n  glTexCoord2f (1, 0);   \r\n  glVertex3f (pos.x - angles[angle].x, -CAR_SIZE, pos.z - angles[angle].y);\r\n  glTexCoord2f (1, 1);   \r\n  glVertex3f (pos.x - angles[angle].x,  top, pos.z - angles[angle].y);\r\n  glTexCoord2f (0, 1);   \r\n  glVertex3f (pos.x + angles[angle].x,  top, pos.z +  angles[angle].y);\r\n  \r\n  glEnd ();\r\n\r\n}"
  },
  {
    "path": "Car.h",
    "content": "class CCar\r\n{\r\n  GLvector        m_position;\r\n  GLvector        m_drive_position;\r\n  bool            m_ready;\r\n  bool            m_front;\r\n  int             m_drive_angle;\r\n  int             m_row;\r\n  int             m_col;\r\n  int             m_direction;\r\n  int             m_change;\r\n  int             m_stuck;\r\n  float           m_speed;\r\n  float           m_max_speed;\r\n\r\npublic:\r\n                  CCar ();\r\n  bool            TestPosition (int row, int col);\r\n  void            Render ();\r\n  void            Update ();\r\n  void            Park () { m_ready = false;}\r\n  class CCar*     m_next;\r\n\r\n};\r\n\r\nvoid  CarClear ();\r\nint   CarCount ();\r\nvoid  CarRender ();\r\nvoid  CarUpdate ();\r\n\r\n"
  },
  {
    "path": "Deco.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Deco.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This handles building and rendering decoration objects - infrastructure & \r\n  such around the city.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define LOGO_OFFSET           0.2f //How far a logo sticks out from the given surface\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n#include <gl\\glu.h>\r\n#include <gl\\glaux.h>\r\n#include \"glTypes.h\"\r\n\r\n#include \"deco.h\"\r\n#include \"light.h\"\r\n#include \"mesh.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"texture.h\"\r\n#include \"world.h\"\r\n#include \"visible.h\"\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCDeco::~CDeco ()\r\n{\r\n\r\n  delete _mesh;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCDeco::CDeco ()\r\n{\r\n\r\n  _mesh = new CMesh ();\r\n  _use_alpha = false;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CDeco::Render ()\r\n{\r\n\r\n  glColor3fv (&_color.red);\r\n  _mesh->Render ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CDeco::RenderFlat (bool colored)\r\n{\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool CDeco::Alpha ()\r\n{ \r\n  \r\n  return _use_alpha; \r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint CDeco::PolyCount ()\r\n{\r\n\r\n  return _mesh->PolyCount ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nunsigned CDeco::Texture ()\r\n{\r\n\r\n  return _texture;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CDeco::CreateRadioTower (GLvector pos, float height)\r\n{\r\n\r\n  CLight*   l;\r\n  float     offset;\r\n  GLvertex  v;\r\n  fan       f;\r\n\r\n  for(int i=0; i<6; i++)\r\n    f.index_list.push_back(i);\r\n\r\n  offset = height / 15.0f;\r\n  _center = pos;\r\n  _use_alpha = true;\r\n  //Radio tower\r\n  v.position = glVector (_center.x, _center.y + height, _center.z);  v.uv = glVector (0,1);\r\n  _mesh->VertexAdd (v);\r\n  v.position = glVector (_center.x - offset, _center.y, _center.z - offset);  v.uv = glVector (1,0);\r\n  _mesh->VertexAdd (v);\r\n  v.position = glVector (_center.x + offset, _center.y, _center.z - offset);  v.uv = glVector (0,0);\r\n  _mesh->VertexAdd (v);\r\n  v.position = glVector (_center.x + offset, _center.y, _center.z + offset);  v.uv = glVector (1,0);\r\n  _mesh->VertexAdd (v);\r\n  v.position = glVector (_center.x - offset, _center.y, _center.z + offset);  v.uv = glVector (0,0);\r\n  _mesh->VertexAdd (v);\r\n  v.position = glVector (_center.x - offset, _center.y, _center.z - offset);  v.uv = glVector (1,0);\r\n  _mesh->VertexAdd (v);\r\n  _mesh->FanAdd (f);\r\n  l = new CLight (glVector (_center.x, _center.y + height + 1.0f, _center.z), glRgba (255,192,160), 1);\r\n  l->Blink ();\r\n  _texture = TextureId (TEXTURE_LATTICE);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CDeco::CreateLogo (GLvector2 start, GLvector2 end, float bottom, int seed, GLrgba color)\r\n{\r\n\r\n  GLvertex   p;\r\n  quad_strip qs;\r\n  float      u1, u2, v1, v2;\r\n  float      top;\r\n  float      height, length;\r\n  GLvector2  center2d;\r\n  GLvector   to;\r\n  GLvector   out;\r\n  int        logo_index;\r\n\r\n  qs.index_list.push_back(0);\r\n  qs.index_list.push_back(1);\r\n  qs.index_list.push_back(3);\r\n  qs.index_list.push_back(2);\r\n\r\n  _use_alpha = true;\r\n  _color = color;\r\n  logo_index = seed % LOGO_ROWS;\r\n  to = glVector (start.x, 0.0f, start.y) - glVector (end.x, 0.0f, end.y);\r\n  to = glVectorNormalize (to);\r\n  out = glVectorCrossProduct (glVector (0.0f, 1.0f, 0.0f), to) * LOGO_OFFSET;\r\n  center2d = (start + end) / 2;\r\n  _center = glVector (center2d.x, bottom, center2d.y);\r\n  length = glVectorLength (start - end);\r\n  height = (length / 8.0f) * 1.5f;\r\n  top = bottom + height;\r\n  u1 = 0.0f;\r\n  u2 = 0.5f;//We actually only use the left half of the texture\r\n  v1 = (float)logo_index / LOGO_ROWS;\r\n  v2 = v1 + (1.0f / LOGO_ROWS);\r\n  p.position = glVector (start.x, bottom, start.y) + out;  p.uv = glVector (u1,v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (end.x, bottom, end.y) + out;  p.uv = glVector (u2, v1);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (end.x, top, end.y) + out;  p.uv = glVector (u2, v2);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (start.x, top, start.y) + out;  p.uv = glVector (u1, v2);\r\n  _mesh->VertexAdd (p);\r\n  _mesh->QuadStripAdd (qs);\r\n  _texture = TextureId (TEXTURE_LOGOS);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CDeco::CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color)\r\n{\r\n\r\n  GLvertex   p;\r\n  quad_strip qs1;\r\n  float      u, v;\r\n  \r\n  qs1.index_list.push_back(0);\r\n  qs1.index_list.push_back(1);\r\n  qs1.index_list.push_back(3);\r\n  qs1.index_list.push_back(2);\r\n  _color = color;\r\n  _use_alpha = true;\r\n  _center = glVector (x + width / 2, height, z + depth / 2);\r\n  if (width < depth) {\r\n    u = 1.0f;\r\n    v = (float)((int)(depth / width));\r\n  } else {\r\n    v = 1.0f;\r\n    u = (float)((int)(width / depth));\r\n  }\r\n  _texture = TextureId (TEXTURE_LIGHT);\r\n  p.position = glVector (x, height, z);  p.uv = glVector (0.0f, 0.0f);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x, height, z + depth);  p.uv = glVector (0.0f, v);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x + width, height, z + depth);  p.uv = glVector (u, v);\r\n  _mesh->VertexAdd (p);\r\n  p.position = glVector (x + width, height, z);  p.uv = glVector (u, 0.0f);\r\n  _mesh->VertexAdd (p);\r\n  _mesh->QuadStripAdd (qs1);\r\n  _mesh->Compile ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CDeco::CreateLightTrim (GLvector* chain, int count, float height, int seed, GLrgba color)\r\n{\r\n\r\n  GLvertex   p;\r\n  GLvector   to;\r\n  GLvector   out;\r\n  int        i;\r\n  int        index;\r\n  int        prev, next;\r\n  float      u, v1, v2;\r\n  float      row;\r\n  quad_strip qs;\r\n\r\n  _color = color;\r\n  _center = glVector (0.0f, 0.0f, 0.0f);\r\n  qs.index_list.reserve(count * 2 + 2);\r\n  for (i = 0; i < count; i++) \r\n    _center += chain[i];\r\n  _center /= (float)count;\r\n  row = (float)(seed % TRIM_ROWS);\r\n  v1 = row * TRIM_SIZE;\r\n  v2 = (row + 1.0f) * TRIM_SIZE;\r\n  index = 0;\r\n  u = 0.0f;\r\n  for (i = 0; i < count + 1; i++) {\r\n    if (i)\r\n      u += glVectorLength (chain[i % count] - p.position) * 0.1f;\r\n    //Add the bottom point      \r\n    prev = i - 1;\r\n    if (prev < 0)\r\n      prev = count + prev;\r\n    next = (i + 1) % count;\r\n    to = glVectorNormalize (chain[next] - chain[prev]);\r\n    out = glVectorCrossProduct (glVector (0.0f, 1.0f, 0.0f), to) * LOGO_OFFSET;\r\n    p.position = chain[i % count] + out; p.uv = glVector (u, v2);\r\n    _mesh->VertexAdd (p);\r\n    qs.index_list.push_back(index++);\r\n    //Top point\r\n    p.position.y += height;p.uv = glVector (u, v1);\r\n    _mesh->VertexAdd (p);\r\n    qs.index_list.push_back(index++);\r\n  }\r\n  _mesh->QuadStripAdd (qs);\r\n  _texture = TextureId (TEXTURE_TRIM);\r\n  _mesh->Compile ();\r\n\r\n}"
  },
  {
    "path": "Deco.h",
    "content": "#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;\r\n  int           _type;\r\n  unsigned      _texture;\r\n  bool          _use_alpha;\r\n\r\npublic:\r\n\r\n                CDeco ();\r\n                ~CDeco ();\r\n  void          CreateLogo (GLvector2 start, GLvector2 end, float base, int seed, GLrgba color);\r\n  void          CreateLightStrip (float x, float z, float width, float depth, float height, GLrgba color);\r\n  void          CreateLightTrim (GLvector* chain, int count, float height, int seed, GLrgba color);\r\n  void          CreateRadioTower (GLvector pos, float height);\r\n  void          Render (void);\r\n  void          RenderFlat (bool colored);\r\n  bool          Alpha ();\r\n  int           PolyCount ();\r\n\r\n  unsigned      Texture ();\r\n\r\n};"
  },
  {
    "path": "Entity.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Entity.cpp\r\n\r\n  Copyright (c) 2005 Shamus Young\r\n  All Rights Reserved\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  An entity is any renderable stationary object in the world.  This is an \r\n  abstract class.  This module gathers up the Entities, sorts them by \r\n  texture use and location, and then stores them in OpenGL render lists\r\n  for faster rendering.    \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n\r\n#include \"camera.h\"\r\n#include \"entity.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"render.h\"\r\n#include \"texture.h\"\r\n#include \"world.h\"\r\n#include \"visible.h\"\r\n#include \"win.h\"\r\n\r\nstruct entity\r\n{\r\n  CEntity*            object;\r\n};\r\n\r\n\r\nstruct cell\r\n{\r\n  unsigned        list_textured;\r\n  unsigned        list_flat;\r\n  unsigned        list_flat_wireframe;\r\n  unsigned        list_alpha;\r\n  GLvector        pos;\r\n};\r\n\r\nstatic cell           cell_list[GRID_SIZE][GRID_SIZE];\r\nstatic int            entity_count;\r\nstatic entity*        entity_list;\r\nstatic bool           sorted;\r\nstatic bool           compiled;\r\nstatic int            polycount;\r\nstatic int            compile_x;\r\nstatic int            compile_y;\r\nstatic int            compile_count;\r\nstatic int            compile_end;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic int do_compare (const void *arg1, const void *arg2 )\r\n{\r\n\r\n  struct entity*  e1 = (struct entity*)arg1;\r\n  struct entity*  e2 = (struct entity*)arg2;\r\n\r\n  if (e1->object->Alpha () && !e2->object->Alpha ())\r\n    return 1;\r\n  if (!e1->object->Alpha () && e2->object->Alpha ())\r\n    return -1;\r\n  if (e1->object->Texture () > e2->object->Texture ())\r\n    return 1;\r\n  else if (e1->object->Texture () < e2->object->Texture ())\r\n    return -1;\r\n  return 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid add (CEntity* b)\r\n{\r\n\r\n  entity_list = (entity*)realloc (entity_list, sizeof (entity) * (entity_count + 1));\r\n  entity_list[entity_count].object = b;\r\n  entity_count++;\r\n  polycount = 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void do_compile ()\r\n{\r\n\r\n  int       i;\r\n  int       x, y;\r\n\r\n  if (compiled)\r\n    return;\r\n  x = compile_x;\r\n  y = compile_y;\r\n  //Changing textures is pretty expensive, and thus sorting the entites so that\r\n  //they are grouped by texture used can really improve framerate.\r\n  //qsort (entity_list, entity_count, sizeof (struct entity), do_compare);\r\n  //sorted = true;\r\n  //Now group entites on the grid \r\n  //make a list for the textured objects in this region\r\n  if (!cell_list[x][y].list_textured)\r\n    cell_list[x][y].list_textured = glGenLists(1);\r\n  glNewList (cell_list[x][y].list_textured, GL_COMPILE);\r\n  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);\r\n  for (i = 0; i < entity_count; i++) {\r\n    GLvector pos = entity_list[i].object->Center ();\r\n    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {\r\n      glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());\r\n      entity_list[i].object->Render ();\r\n    }\r\n  }\r\n  glEndList();\t\r\n\r\n  //Make a list of flat-color stuff (A/C units, ledges, roofs, etc.)\r\n  if (!cell_list[x][y].list_flat)\r\n    cell_list[x][y].list_flat = glGenLists(1);\r\n  glNewList (cell_list[x][y].list_flat, GL_COMPILE);\r\n  glEnable (GL_CULL_FACE);\r\n  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);\r\n  for (i = 0; i < entity_count; i++) {\r\n    GLvector pos = entity_list[i].object->Center ();\r\n    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {\r\n      entity_list[i].object->RenderFlat (false);\r\n    }\r\n  }\r\n  glEndList();\t\r\n  //Now a list of flat-colored stuff that will be wireframe friendly\r\n  if (!cell_list[x][y].list_flat_wireframe)\r\n    cell_list[x][y].list_flat_wireframe = glGenLists(1);\r\n  glNewList (cell_list[x][y].list_flat_wireframe, GL_COMPILE);\r\n  glEnable (GL_CULL_FACE);\r\n  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);\r\n  for (i = 0; i < entity_count; i++) {\r\n    GLvector pos = entity_list[i].object->Center ();\r\n    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && !entity_list[i].object->Alpha ()) {\r\n      entity_list[i].object->RenderFlat (true);\r\n    }\r\n  }\r\n  glEndList();\t\r\n  //Now a list of stuff to be alpha-blended, and thus rendered last\r\n  if (!cell_list[x][y].list_alpha)\r\n    cell_list[x][y].list_alpha = glGenLists(1);\r\n  glNewList (cell_list[x][y].list_alpha, GL_COMPILE);\r\n  cell_list[x][y].pos = glVector (GRID_TO_WORLD(x), 0.0f, (float)y * GRID_RESOLUTION);\r\n  glDepthMask (false);\r\n  glEnable (GL_BLEND);\r\n  glDisable (GL_CULL_FACE);\r\n  for (i = 0; i < entity_count; i++) {\r\n    GLvector pos = entity_list[i].object->Center ();\r\n    if (WORLD_TO_GRID(pos.x) == x && WORLD_TO_GRID(pos.z) == y && entity_list[i].object->Alpha ()) {\r\n      glBindTexture(GL_TEXTURE_2D, entity_list[i].object->Texture ());\r\n      entity_list[i].object->Render ();\r\n    }\r\n  }\r\n  glDepthMask (true);\r\n  glEndList();\t\r\n\r\n  //now walk the grid\r\n  compile_x++;\r\n  if (compile_x == GRID_SIZE) {\r\n    compile_x = 0;\r\n    compile_y++;\r\n    if (compile_y == GRID_SIZE)\r\n      compiled = true;\r\n    compile_end = GetTickCount ();\r\n  } \r\n  compile_count++;\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool EntityReady ()\r\n{\r\n\r\n  return compiled;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat EntityProgress ()\r\n{\r\n\r\n  return (float)compile_count / (GRID_SIZE * GRID_SIZE);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid EntityUpdate ()\r\n{\r\n\r\n  unsigned    stop_time;\r\n\r\n  if (!TextureReady ()) {\r\n    sorted = false;\r\n    return;\r\n  } \r\n  if (!sorted) {\r\n    qsort (entity_list, entity_count, sizeof (struct entity), do_compare);\r\n    sorted = true;\r\n  }\r\n  //We want to do several cells at once. Enough to get things done, but\r\n  //not so many that the program is unresponsive.\r\n  if (LOADING_SCREEN) {  //If we're using a loading screen, we want to build as fast as possible\r\n    stop_time = GetTickCount () + 100;\r\n    while (!compiled && GetTickCount () < stop_time)\r\n      do_compile ();\r\n  } else //Take it slow\r\n    do_compile ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid EntityRender ()\r\n{\r\n\r\n  int       polymode[2];\r\n  bool      wireframe;\r\n  int       x, y;\r\n  int       elapsed;\r\n\r\n  //Draw all textured objects\r\n  glGetIntegerv (GL_POLYGON_MODE, &polymode[0]);\r\n  wireframe = polymode[0] != GL_FILL;\r\n  if (RenderFlat ())\r\n    glDisable (GL_TEXTURE_2D);\r\n  //If we're not using a loading screen, make the wireframe fade out via fog\r\n  if (!LOADING_SCREEN && wireframe) {\r\n    elapsed = 6000 - WorldSceneElapsed ();\r\n    if (elapsed >= 0 && elapsed <= 6000)\r\n      RenderFogFX ((float)elapsed / 6000.0f);\r\n    else\r\n      return;\r\n  }\r\n  for (x = 0; x < GRID_SIZE; x++) {\r\n    for (y = 0; y < GRID_SIZE; y++) {\r\n      if (Visible (x,y))\r\n        glCallList (cell_list[x][y].list_textured);\r\n    }\r\n  }\r\n  //draw all flat colored objects\r\n  glBindTexture(GL_TEXTURE_2D, 0);\r\n  glColor3f (0, 0, 0);\r\n  for (x = 0; x < GRID_SIZE; x++) {\r\n    for (y = 0; y < GRID_SIZE; y++) {\r\n      if (Visible (x, y)) {\r\n        if (wireframe)\r\n          glCallList (cell_list[x][y].list_flat_wireframe);\r\n        else \r\n          glCallList (cell_list[x][y].list_flat);\r\n      }\r\n    }\r\n  }\r\n  //draw all alpha-blended objects\r\n  glBindTexture(GL_TEXTURE_2D, 0);\r\n  glColor3f (0, 0, 0);\r\n  glEnable (GL_BLEND);\r\n  for (x = 0; x < GRID_SIZE; x++) {\r\n    for (y = 0; y < GRID_SIZE; y++) {\r\n      if (Visible (x,y)) {\r\n        glCallList (cell_list[x][y].list_alpha);\r\n      }\r\n    }\r\n  }\r\n  \r\n}\r\n\r\n\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid EntityClear ()\r\n{\r\n\r\n  for (int i = 0; i < entity_count; i++) {\r\n    delete entity_list[i].object;\r\n  }\r\n  if (entity_list)\r\n    free (entity_list);\r\n  entity_list = NULL;\r\n  entity_count = 0;\r\n  compile_x = 0;\r\n  compile_y = 0;\r\n  compile_count = 0;\r\n  compiled = false;\r\n  sorted = false;\r\n\r\n  int  x, y;\r\n\r\n  for (x = 0; x < GRID_SIZE; x++) {\r\n    for (y = 0; y < GRID_SIZE; y++) {\r\n      glNewList (cell_list[x][y].list_textured, GL_COMPILE);\r\n      glEndList();\t\r\n      glNewList (cell_list[x][y].list_alpha, GL_COMPILE);\r\n      glEndList();\t\r\n      glNewList (cell_list[x][y].list_flat_wireframe, GL_COMPILE);\r\n      glEndList();\t\r\n      glNewList (cell_list[x][y].list_flat, GL_COMPILE);\r\n      glEndList();\t\r\n    }\r\n  }\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint EntityCount ()\r\n{\r\n\r\n  return entity_count;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid EntityInit (void)\r\n{\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint EntityPolyCount (void)\r\n{\r\n\r\n  if (!sorted)\r\n    return 0;\r\n  if (polycount)\r\n    return polycount;\r\n  for (int i = 0; i < entity_count; i++) \r\n    polycount += entity_list[i].object->PolyCount ();\r\n  return polycount;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCEntity::CEntity (void)\r\n{\r\n\r\n  add (this);\r\n\r\n}\r\n\r\nvoid CEntity::Render (void)\r\n{\r\n\r\n}\r\n\r\nvoid CEntity::RenderFlat (bool wireframe)\r\n{\r\n\r\n}\r\n\r\nvoid CEntity::Update (void)\r\n{\r\n\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "Entity.h",
    "content": "#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:\r\n\r\n  GLvector                _center;\r\n\r\npublic:\r\n                          CEntity (void);\r\n  virtual                 ~CEntity () {};\r\n  virtual void            Render (void);\r\n  virtual void            RenderFlat (bool wirefame);\r\n  virtual unsigned        Texture () { return 0; }\r\n  virtual void            Update (void);\r\n  virtual bool            Alpha () { return false; }\r\n  virtual int             PolyCount () { return 0; }\r\n  GLvector                Center () { return _center; }\r\n\r\n};\r\n\r\nvoid      EntityClear ();\r\nint       EntityCount (void);\r\nfloat     EntityProgress ();\r\nbool      EntityReady ();\r\nvoid      EntityRender (void);\r\nvoid      EntityUpdate (void);\r\nint       EntityPolyCount (void);\r\n\r\n#endif"
  },
  {
    "path": "Ini.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Ini.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n\r\n-------------------------------------------------------------------------------\r\n  \r\n  This takes various types of data and dumps them into a predefined ini file.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define FORMAT_VECTOR       \"%f %f %f\"\r\n#define MAX_RESULT          256\r\n#define FORMAT_FLOAT        \"%1.2f\"\r\n#define INI_FILE            \".\\\\\" APP \".ini\"\r\n#define SECTION             \"Settings\"\r\n\r\n#include <windows.h>\r\n#include <stdio.h>\r\n#include \"glTypes.h\"\r\n\r\n#include \"ini.h\"\r\n#include \"win.h\"\r\n\r\nstatic char                 result[MAX_RESULT];\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint IniInt (char* entry)\r\n{\r\n\r\n  int         result;\r\n\r\n  result = GetPrivateProfileInt (SECTION, entry, 0, INI_FILE);\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid IniIntSet (char* entry, int val)\r\n{\r\n\r\n  char        buf[20];\r\n\r\n  sprintf (buf, \"%d\", val);\r\n  WritePrivateProfileString (SECTION, entry, buf, INI_FILE);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat IniFloat (char* entry)\r\n{\r\n\r\n  float     f;\r\n\r\n  GetPrivateProfileString (SECTION, entry, \"\", result, MAX_RESULT, INI_FILE);\r\n  f = (float)atof (result);\r\n  return f;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid IniFloatSet (char* entry, float val)\r\n{\r\n\r\n  char        buf[20];\r\n  \r\n  sprintf (buf, FORMAT_FLOAT, val);\r\n  WritePrivateProfileString (SECTION, entry, buf, INI_FILE);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nchar* IniString (char* entry)\r\n{\r\n\r\n  GetPrivateProfileString (SECTION, entry, \"\", result, MAX_RESULT, INI_FILE);\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid IniStringSet (char* entry, char* val)\r\n{\r\n\r\n  WritePrivateProfileString (SECTION, entry, val, INI_FILE);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid IniVectorSet (char* entry, GLvector v)\r\n{\r\n  \r\n  sprintf (result, FORMAT_VECTOR, v.x, v.y, v.z);\r\n  WritePrivateProfileString (SECTION, entry, result, INI_FILE);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector IniVector (char* entry)\r\n{\r\n\r\n  GLvector  v;\r\n\r\n  v.x = v.y = v.z = 0.0f;\r\n  GetPrivateProfileString (SECTION, entry, \"0 0 0\", result, MAX_RESULT, INI_FILE);\r\n  sscanf (result, FORMAT_VECTOR, &v.x, &v.y, &v.z);\r\n  return v;\r\n\r\n}\r\n"
  },
  {
    "path": "Ini.h",
    "content": "int       IniInt (char* entry);\r\nvoid      IniIntSet (char* entry, int val);\r\nfloat     IniFloat (char* entry);\r\nvoid      IniFloatSet (char* entry, float val);\r\nchar*     IniString (char* entry);\r\nvoid      IniStringSet (char* entry, char* val);\r\nvoid      IniVectorSet (char* entry, GLvector v);\r\nGLvector  IniVector (char* entry);\r\n"
  },
  {
    "path": "Light.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Light.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This tracks and renders the light sources. (Note that they do not really \r\n  CAST light in the OpenGL sense of the world, these are just simple panels.) \r\n  These are NOT subclassed to entities because these are dynamic.  Some lights \r\n  blink, and thus they can't go into the fixed render lists managed by \r\n  Entity.cpp.  \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define MAX_SIZE            5\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n#include <gl\\glu.h>\r\n#include <gl\\glaux.h>\r\n#include \"glTypes.h\"\r\n\r\n#include \"camera.h\"\r\n#include \"entity.h\"\r\n#include \"light.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"texture.h\"\r\n#include \"visible.h\"\r\n\r\nstatic GLvector2      angles[5][360];\r\nstatic CLight*        head;\r\nstatic bool           angles_done;\r\nstatic int            count;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid LightClear ()\r\n{\r\n\r\n  CLight*   l;\r\n\r\n  while (head) {\r\n    l = head;\r\n    head = l->_next;\r\n    delete l;\r\n  }\r\n  count = 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint LightCount ()\r\n{\r\n\r\n  return count;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid LightRender ()\r\n{\r\n\r\n  CLight*     l;\r\n\r\n  if (!EntityReady ())\r\n    return;\r\n  if (!angles_done) {\r\n    for (int size = 0; size < MAX_SIZE; size++) {\r\n      for (int i = 0 ;i < 360; i++) {\r\n        angles[size][i].x = cosf ((float)i * DEGREES_TO_RADIANS) * ((float)size + 0.5f);\r\n        angles[size][i].y = sinf ((float)i * DEGREES_TO_RADIANS) * ((float)size + 0.5f);\r\n      }\r\n    }\r\n  }\r\n  glDepthMask (false);\r\n  glEnable (GL_BLEND);\r\n  glDisable (GL_CULL_FACE);\r\n  glBlendFunc (GL_ONE, GL_ONE);\r\n  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_LIGHT));\r\n  glDisable (GL_CULL_FACE);\r\n  glBegin (GL_QUADS);\r\n  for (l = head; l; l = l->_next) \r\n    l->Render ();\r\n  glEnd ();\r\n  glDepthMask (true);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCLight::CLight (GLvector pos, GLrgba color, int size)\r\n{\r\n\r\n  _position = pos;\r\n  _color = color;\r\n  _size = CLAMP (size, 0, (MAX_SIZE - 1));\r\n  _vert_size = (float)_size + 0.5f;\r\n  _flat_size = _vert_size + 0.5f;\r\n  _blink = false;\r\n  _cell_x = WORLD_TO_GRID(pos.x);\r\n  _cell_z = WORLD_TO_GRID(pos.z);\r\n  _next = head;\r\n  head = this;\r\n  count++;\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CLight::Blink ()\r\n{\r\n\r\n  _blink = true;\r\n  //we don't want blinkers to be in sync, so have them blink at \r\n  //slightly different rates. (Milliseconds)\r\n  _blink_interval = 1500 + RandomVal (500);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CLight::Render ()\r\n{\r\n\r\n  int       angle;\r\n  GLvector  pos;\r\n  GLvector  camera;\r\n  GLvector  camera_position;\r\n  GLvector2 offset;\r\n\r\n  if (!Visible (_cell_x, _cell_z))\r\n    return;\r\n  camera = CameraAngle ();\r\n  camera_position = CameraPosition ();\r\n  if (fabs (camera_position.x - _position.x) > RenderFogDistance ())\r\n    return;\r\n  if (fabs (camera_position.z - _position.z) > RenderFogDistance ())\r\n    return;\r\n  if (_blink && (GetTickCount () % _blink_interval) > 200)\r\n    return;\r\n  angle = (int)MathAngle (camera.y);\r\n  offset = angles[_size][angle];\r\n  pos = _position;\r\n  glColor4fv (&_color.red);\r\n  glTexCoord2f (0, 0);   \r\n  glVertex3f (pos.x + offset.x, pos.y - _vert_size, pos.z + offset.y);\r\n  glTexCoord2f (0, 1);   \r\n  glVertex3f (pos.x - offset.x, pos.y - _vert_size, pos.z - offset.y);\r\n  glTexCoord2f (1, 1);   \r\n  glVertex3f (pos.x - offset.x, pos.y + _vert_size, pos.z - offset.y);\r\n  glTexCoord2f (1, 0);   \r\n  glVertex3f (pos.x + offset.x, pos.y + _vert_size, pos.z + offset.y);\r\n\r\n}"
  },
  {
    "path": "Light.h",
    "content": "class CLight\r\n{\r\n  GLvector        _position;\r\n  GLrgba          _color;\r\n  int             _size;\r\n  float           _vert_size;\r\n  float           _flat_size;\r\n  bool            _blink;\r\n  unsigned        _blink_interval;\r\n  int             _cell_x;\r\n  int             _cell_z;\r\n\r\npublic:\r\n                  CLight(GLvector pos, GLrgba color, int size);\r\n  class CLight*   _next;\r\n  void            Render ();\r\n  void            Blink ();\r\n\r\n};\r\n\r\nvoid  LightRender ();\r\nvoid  LightClear ();\r\nint   LightCount ();\r\n"
  },
  {
    "path": "Macro.h",
    "content": "#define LIMIT_INTERVAL(interval)  { static unsigned next_update; if (next_update > GetTickCount ()) return; next_update = GetTickCount () + interval;}\r\n#define DEGREES_TO_RADIANS        .017453292F\r\n#define RADIANS_TO_DEGREES        57.29577951F\r\n#define PI                        ((double)3.1415926535F)\r\n#define PI2                       PI*PI\r\n#define GRAVITY                   9.5f\r\n#define CLAMP(a,b,c)              (a < b ? b : (a > c ? c : a))\r\n#define WRAP(x,y)                 ((unsigned)x % y)\r\n#define SIGN(x)                   (((x) > 0) ? 1 : ((x) < 0) ? -1 : 0)\r\n#define ABS(x)                    (((x) < 0 ? (-x) : (x)))\r\n#define SMALLEST(x,y)             (ABS(x) < ABS(y) ? 0 : x)                \r\n#define MIN(x,y)                  ((x) < (y) ? x : y)                \r\n#define MAX(x,y)                  ((x) > (y) ? x : y)                \r\n#define POW(x,y)                  (float)pow(x,y)\r\n#define SWAP(a,b)                 {int temp = a;a = b; b = temp;}\r\n"
  },
  {
    "path": "Math.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Math.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n  \r\n  Various useful math functions.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <math.h>\r\n\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n\r\n/*-----------------------------------------------------------------------------\r\nKeep an angle between 0 and 360\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathAngle (float angle)\r\n{\r\n\r\n  if (angle < 0.0f) \r\n    angle = 360.0f - (float)fmod (fabs (angle), 360.0f);\r\n  else\r\n    angle = (float)fmod (angle, 360.0f);\r\n  return angle;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nGet an angle between two given points on a grid\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathAngle (float x1, float y1, float x2, float y2)\r\n{\r\n\r\n  float   x_delta;\r\n  float   z_delta;\r\n  float   angle;\r\n\r\n  z_delta = (y1 - y2);\r\n  x_delta = (x1 - x2); \r\n  if (x_delta == 0) {\r\n    if (z_delta > 0)\r\n      return 0.0f;\r\n    else\r\n      return 180.0f;\r\n  }\r\n  if (fabs (x_delta) < fabs (z_delta)) {\r\n    angle = 90 - (float)atan (z_delta / x_delta) * RADIANS_TO_DEGREES;\r\n    if (x_delta < 0)\r\n      angle -= 180.0f;\r\n  } else {\r\n    angle = (float)atan (x_delta / z_delta) * RADIANS_TO_DEGREES;\r\n    if (z_delta < 0.0f)\r\n      angle += 180.0f;\r\n  }\r\n  if (angle< 0.0f)\r\n    angle += 360.0f;\r\n  return angle;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nGet distance (squared) between 2 points on a plane\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathDistance2 (float x1, float y1, float x2, float y2)\r\n{\r\n\r\n  float     dx;\r\n  float     dy;\r\n\r\n  dx = x1 - x2;\r\n  dy = y1 - y2;\r\n  return dx * dx + dy * dy;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nGet distance between 2 points on a plane. This is slightly slower than \r\nMathDistance2 ()\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathDistance (float x1, float y1, float x2, float y2)\r\n{\r\n\r\n  float     dx;\r\n  float     dy;\r\n\r\n  dx = x1 - x2;\r\n  dy = y1 - y2;\r\n  return (float)sqrt (dx * dx + dy * dy);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\ndifference between two angles\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathAngleDifference (float a1, float a2)\r\n\r\n{\r\n\r\n  float         result;\r\n\r\n  result = (float)fmod (a1 - a2, 360.0f);\r\n  if (result > 180.0)\r\n    return result - 360.0F;\r\n  if (result < -180.0)\r\n    return result + 360.0F;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\ninterpolate between two values\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathInterpolate (float n1, float n2, float delta)\r\n{\r\n\r\n  return n1 * (1.0f - delta) + n2 * delta;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nreturn a scalar of 0.0 to 1.0, based an the given values position within a range\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathSmoothStep (float val, float a, float b)\r\n{\r\n\r\n  if (b == a)\r\n    return 0.0f;\r\n  val -= a;\r\n  val /= (b - a);\r\n  return CLAMP (val, 0.0f, 1.0f);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nAverage two values\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathAverage (float n1, float n2)\r\n{\r\n\r\n  return (n1 + n2) / 2.0f;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n  This will take linear input values from 0.0 to 1.0 and convert them to \r\n  values along a curve.  This could also be acomplished with sin (), but this \r\n  way avoids converting to radians and back.\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat MathScalarCurve (float val)\r\n{\r\n \r\n  float   sign;\r\n\r\n  val = (val - 0.5f) * 2.0f;\r\n  if (val < 0.0f)\r\n    sign = -1.0f;\r\n  else \r\n    sign = 1.0f;\r\n  if (val < 0.0f) \r\n    val = -val;\r\n  val = 1.0f - val;\r\n  val *= val;\r\n  val = 1.0f - val;\r\n  val *= sign;\r\n  val = (val + 1.0f) / 2.0f;\r\n  return val;\r\n\r\n}"
  },
  {
    "path": "Math.h",
    "content": "float MathAngle (float angle);\r\nfloat MathAngle (float x1, float y1, float x2, float y2);\r\nfloat MathAngleDifference (float a1, float a2);\r\nfloat MathAverage (float n1, float n2);\r\nfloat MathInterpolate (float n1, float n2, float delta);\r\nfloat MathLine_distance (float x1, float y1, float x2, float y2, float px, float py);\r\nfloat MathDistance (float x1, float y1, float x2, float y2);\r\nfloat MathDistance2 (float x1, float y1, float x2, float y2);\r\nfloat MathSmoothStep (float val, float a, float b);\r\nfloat MathScalarCurve (float val);"
  },
  {
    "path": "Mesh.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Mesh.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This class is used to make constructing objects easier. It handles\r\n  allocating vertex lists, polygon lists, and suchlike. \r\n\r\n  If you were going to implement vertex buffers, this would be the place to \r\n  do it.  Take away the _vertex member variable and store verts for ALL meshes\r\n  in a common list, which could then be unloaded onto the good 'ol GPU.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <windows.h>\r\n#include <GL/gl.h>\r\n#include <GL/glu.h>\r\n\r\n#include <vector>\r\n#include \"glTypes.h\"\r\n#include \"Mesh.h\"\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCMesh::CMesh ()\r\n{\r\n\r\n  _list = glGenLists(1);\r\n  _compiled = false;\r\n  _polycount = 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCMesh::~CMesh ()\r\n{\r\n\r\n  glDeleteLists (_list, 1);\r\n  _vertex.clear ();\r\n  _fan.clear ();\r\n  _quad_strip.clear ();\r\n  _cube.clear ();\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CMesh::VertexAdd (const GLvertex& v)\r\n{\r\n\r\n  _vertex.push_back(v);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CMesh::CubeAdd (const cube& c)\r\n{\r\n\r\n  _cube.push_back(c);\r\n  _polycount += 5;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CMesh::QuadStripAdd (const quad_strip& qs)\r\n{\r\n\r\n  _quad_strip.push_back(qs);\r\n  _polycount += (qs.index_list.size() - 2) / 2;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CMesh::FanAdd (const fan& f)\r\n{\r\n\r\n  _fan.push_back(f);\r\n  _polycount += f.index_list.size() - 2;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CMesh::Render ()\r\n{\r\n\r\n  std::vector<quad_strip>::iterator qsi;\r\n  std::vector<cube>::iterator ci;\r\n  std::vector<fan>::iterator fi;\r\n  std::vector<int>::iterator n;\r\n\r\n  if (_compiled) {\r\n    glCallList (_list);\r\n    return;\r\n  }\r\n  for (qsi = _quad_strip.begin(); qsi < _quad_strip.end(); ++qsi) {\r\n    glBegin (GL_QUAD_STRIP);\r\n    for (n = qsi->index_list.begin(); n < qsi->index_list.end(); ++n) {\r\n      glTexCoord2fv (&_vertex[*n].uv.x);\r\n      glVertex3fv (&_vertex[*n].position.x);\r\n    }\r\n    glEnd ();\r\n  }\r\n  for (ci = _cube.begin(); ci < _cube.end(); ++ci) {\r\n    glBegin (GL_QUAD_STRIP);\r\n    for (n = ci->index_list.begin(); n < ci->index_list.end(); ++n) {\r\n      glTexCoord2fv (&_vertex[*n].uv.x);\r\n      glVertex3fv (&_vertex[*n].position.x);\r\n    }\r\n    glEnd ();\r\n    \r\n    glBegin (GL_QUADS);\r\n    glTexCoord2fv (&_vertex[ci->index_list[7]].uv.x);\r\n    glVertex3fv (&_vertex[ci->index_list[7]].position.x);\r\n    glVertex3fv (&_vertex[ci->index_list[5]].position.x);\r\n    glVertex3fv (&_vertex[ci->index_list[3]].position.x);\r\n    glVertex3fv (&_vertex[ci->index_list[1]].position.x);\r\n    glEnd ();\r\n    \r\n    glBegin (GL_QUADS);\r\n    glTexCoord2fv (&_vertex[ci->index_list[6]].uv.x);\r\n    glVertex3fv (&_vertex[ci->index_list[0]].position.x);\r\n    glVertex3fv (&_vertex[ci->index_list[2]].position.x);\r\n    glVertex3fv (&_vertex[ci->index_list[4]].position.x);\r\n    glVertex3fv (&_vertex[ci->index_list[6]].position.x);\r\n    glEnd ();\r\n\r\n  \r\n  }\r\n  for (fi = _fan.begin(); fi < _fan.end(); ++fi) {\r\n    glBegin (GL_TRIANGLE_FAN);\r\n    for (n = fi->index_list.begin(); n < fi->index_list.end(); ++n) {\r\n      glTexCoord2fv (&_vertex[*n].uv.x);\r\n      glVertex3fv (&_vertex[*n].position.x);\r\n    }\r\n    glEnd ();\r\n  }\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CMesh::Compile ()\r\n{\r\n\r\n  glNewList (_list, GL_COMPILE);\r\n  Render ();\r\n  glEndList();\t\r\n  _compiled = true;\r\n\r\n}\r\n"
  },
  {
    "path": "Mesh.h",
    "content": "\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\nstruct quad_strip\r\n{\r\n  std::vector<int> index_list;\r\n};\r\n\r\nstruct fan\r\n{\r\n  std::vector<int> index_list;\r\n};\r\n\r\nclass CMesh\r\n{\r\npublic:\r\n                          CMesh ();\r\n                          ~CMesh ();\r\n  unsigned                _list;\r\n  int                     _polycount;\r\n  std::vector<GLvertex>   _vertex;  \r\n  std::vector<cube>       _cube;\r\n  std::vector<quad_strip> _quad_strip;\r\n  std::vector<fan>        _fan;\r\n  bool                    _compiled;\r\n\r\n  void        VertexAdd (const GLvertex& v);\r\n  int         VertexCount () { return _vertex.size(); }\r\n  int         PolyCount () { return _polycount; }\r\n  void        CubeAdd (const cube& c);\r\n  void        QuadStripAdd (const quad_strip& qs);\r\n  void        FanAdd (const fan& f);\r\n  void        Render ();\r\n  void        Compile ();\r\n\r\n};\r\n"
  },
  {
    "path": "PixelCity.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"PixelCity\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Application\" 0x0101\r\n\r\nCFG=PixelCity - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"PixelCity.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"PixelCity.mak\" CFG=\"PixelCity - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"PixelCity - Win32 Release\" (based on \"Win32 (x86) Application\")\r\n!MESSAGE \"PixelCity - Win32 Debug\" (based on \"Win32 (x86) Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"PixelCity\"\r\n# PROP Scc_LocalPath \".\"\r\nCPP=cl.exe\r\nMTL=midl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"PixelCity - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"Release\"\r\n# PROP BASE Intermediate_Dir \"Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"Release\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# 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\r\n# 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\"\r\n\r\n!ELSEIF  \"$(CFG)\" == \"PixelCity - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"Debug\"\r\n# PROP BASE Intermediate_Dir \"Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"Debug\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# 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\r\n# 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\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"PixelCity - Win32 Release\"\r\n# Name \"PixelCity - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Group \"glTypes\"\r\n\r\n# PROP Default_Filter \"\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\glBbox.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\glMatrix.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\glQuat.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\glRgba.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\glVector2.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\glVector3.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Source File\r\n\r\nSOURCE=.\\Building.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Camera.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Car.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Deco.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Entity.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Ini.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Light.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Math.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Mesh.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Random.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Render.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Sky.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Texture.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Visible.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Win.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\World.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\Building.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Camera.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Car.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Deco.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Entity.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\glTypes.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Ini.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Light.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Macro.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Math.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Mesh.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Random.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Render.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Sky.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Texture.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Visible.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\Win.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\World.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "Random.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\t\t\t\t\t\t\t\t\t               r a n d o m\r\n-----------------------------------------------------------------------------*/\r\n\r\n/*-----------------------------------------------------------------------------\r\n  The Mersenne Twister by Matsumoto and Nishimura <matumoto@math.keio.ac.jp>.\r\n  It sets new standards for the period, quality and speed of random number\r\n  generators. The incredible period is 2^19937 - 1, a number with about 6000\r\n  digits; the 32-bit random numbers exhibit best possible equidistribution\r\n  properties in dimensions up to 623; and it's fast, very fast. \r\n-----------------------------------------------------------------------------*/\r\n\r\n\r\n#define LOWER_MASK            0x7fffffff \r\n#define M                     397\r\n#define MATRIX_A              0x9908b0df \r\n#define N                     624\r\n#define TEMPERING_MASK_B      0x9d2c5680\r\n#define TEMPERING_MASK_C      0xefc60000\r\n#define TEMPERING_SHIFT_L(y)  (y >> 18)\r\n#define TEMPERING_SHIFT_S(y)  (y << 7)\r\n#define TEMPERING_SHIFT_T(y)  (y << 15)\r\n#define TEMPERING_SHIFT_U(y)  (y >> 11)\r\n#define UPPER_MASK            0x80000000 \r\n\r\n#include <memory.h>\r\n#include \"random.h\"\r\n\r\nstatic int              k = 1;\r\nstatic unsigned long    mag01[2] = {0x0, MATRIX_A};\r\nstatic unsigned long    ptgfsr[N];\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nunsigned long RandomVal (void)\r\n{\r\n\r\n  int\t\t            kk;\r\n  unsigned long\t    y;\r\n  \r\n  if (k == N) {\r\n    for (kk = 0; kk < N - M; kk++) {\r\n      y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);\r\n      ptgfsr[kk] = ptgfsr[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];\r\n      }\r\n    for (; kk < N - 1; kk++) {\r\n      y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);\r\n      ptgfsr[kk] = ptgfsr[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];\r\n      }\r\n    y = (ptgfsr[N - 1] & UPPER_MASK) | (ptgfsr[0] & LOWER_MASK);\r\n    ptgfsr[N - 1] = ptgfsr[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];\r\n    k = 0;\r\n    }\r\n  y = ptgfsr[k++];\r\n  y ^= TEMPERING_SHIFT_U (y);\r\n  y ^= TEMPERING_SHIFT_S (y) & TEMPERING_MASK_B;\r\n  y ^= TEMPERING_SHIFT_T (y) & TEMPERING_MASK_C;\r\n  return y ^= TEMPERING_SHIFT_L (y);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nunsigned long RandomVal (int range)\r\n{\r\n\r\n  return range ? (RandomVal () % range) : 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RandomInit (unsigned long seed)\r\n{\r\n\r\n  //int\t    k;\r\n  \r\n  //memset (ptgfsr, 0, sizeof (ptgfsr));\r\n  //mag01[0] = 0x0;\r\n  //mag01[1] = MATRIX_A;\r\n  ptgfsr[0] = seed;\r\n  for (k = 1; k < N; k++)\r\n    ptgfsr[k] = 69069 * ptgfsr[k - 1];\r\n  k = 1;\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "Random.h",
    "content": "#define COIN_FLIP     (RandomVal (2) == 0)\r\n\r\nunsigned long RandomVal (int range);\r\nunsigned long RandomVal (void);\r\nvoid          RandomInit (unsigned long seed);\r\n"
  },
  {
    "path": "Render.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Render.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n  \r\n  This is the core of the gl rendering functions.  This contains the main \r\n  rendering function RenderUpdate (), which initiates the various \r\n  other renders in the other modules. \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define RENDER_DISTANCE     1280\r\n#define MAX_TEXT            256\r\n#define YOUFAIL(message)    {WinPopup (message);return;}\r\n#define HELP_SIZE           sizeof(help)\r\n#define COLOR_CYCLE_TIME    10000 //milliseconds\r\n#define COLOR_CYCLE         (COLOR_CYCLE_TIME / 4)\r\n#define FONT_COUNT          (sizeof (fonts) / sizeof (struct glFont))\r\n#define FONT_SIZE           (LOGO_PIXELS - LOGO_PIXELS / 8)\r\n#define BLOOM_SCALING       0.07f\r\n\r\n#include <windows.h>\r\n#include <stdio.h>\r\n#include <time.h>\r\n#include <stdarg.h>\r\n#include <math.h>\r\n\r\n#include <gl\\gl.h>\r\n#include <gl\\glu.h>\r\n\r\n#include \"gltypes.h\"\r\n#include \"entity.h\"\r\n#include \"car.h\"\r\n#include \"camera.h\"\r\n#include \"ini.h\"\r\n#include \"light.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"render.h\"\r\n#include \"sky.h\"\r\n#include \"texture.h\"\r\n#include \"world.h\"\r\n#include \"win.h\"\r\n\r\nstatic\tPIXELFORMATDESCRIPTOR pfd =\t\t\t\r\n{\r\n\tsizeof(PIXELFORMATDESCRIPTOR),\t\t\t\r\n\t1,\t\t\t\t\t\t\t\t\t\t\t  // Version Number\r\n\tPFD_DRAW_TO_WINDOW |\t\t\t// Format Must Support Window\r\n\tPFD_SUPPORT_OPENGL |\t\t\t// Format Must Support OpenGL\r\n\tPFD_DOUBLEBUFFER,\t\t\t\t\t// Must Support Double Buffering\r\n\tPFD_TYPE_RGBA,\t\t\t\t\t\t// Request An RGBA Format\r\n\t32,\t\t\t\t\t\t\t\t\t\t    // Select Our glRgbaDepth\r\n\t0, 0, 0, 0, 0, 0,\t\t\t\t\t// glRgbaBits Ignored\r\n\t0,\t\t\t\t\t\t\t\t\t\t\t  // No Alpha Buffer\r\n\t0,\t\t\t\t\t\t\t\t\t\t\t  // Shift Bit Ignored\r\n\t0,\t\t\t\t\t\t\t\t\t\t\t  // Accumulation Buffers\r\n\t0, 0, 0, 0,\t\t\t\t\t\t\t\t// Accumulation Bits Ignored\r\n\t16,\t\t\t\t\t\t\t\t\t\t\t  // Z-Buffer (Depth Buffer)  bits\r\n\t0,\t\t\t\t\t\t\t\t\t\t\t  // Stencil Buffers\r\n\t1,\t\t\t\t\t\t\t\t\t\t\t  // Auxiliary Buffers\r\n\tPFD_MAIN_PLANE,\t\t\t\t\t\t// Main Drawing Layer\r\n\t0,\t\t\t\t\t\t\t\t\t\t\t  // Reserved\r\n\t0, 0, 0\t\t\t\t\t\t\t\t\t\t// Layer Masks Ignored\r\n};\r\n\r\nstatic char             help[] = \r\n  \"ESC - Exit!\\n\" \r\n  \"F1  - Show this help screen\\n\" \r\n  \"R   - Rebuild city\\n\" \r\n  \"L   - Toggle 'letterbox' mode\\n\"\r\n  \"F   - Show Framecounter\\n\"\r\n  \"W   - Toggle Wireframe\\n\"\r\n  \"E   - Change full-scene effects\\n\"\r\n  \"T   - Toggle Textures\\n\"\r\n  \"G   - Toggle Fog\\n\"\r\n;\r\n\r\nstruct glFont\r\n{\r\n  char*         name;\r\n  unsigned\t\t  base_char;\r\n} fonts[] = \r\n{\r\n  \"Courier New\",      0,\r\n  \"Arial\",            0,\r\n  \"Times New Roman\",  0,\r\n  \"Arial Black\",      0,\r\n  \"Impact\",           0,\r\n  \"Agency FB\",        0,\r\n  \"Book Antiqua\",     0,\r\n};\r\n\r\n#if SCREENSAVER\r\nenum\r\n{\r\n  EFFECT_NONE,\r\n  EFFECT_BLOOM,\r\n  EFFECT_BLOOM_RADIAL,\r\n  EFFECT_COLOR_CYCLE,\r\n  EFFECT_GLASS_CITY,\r\n  EFFECT_COUNT,\r\n  EFFECT_DEBUG,\r\n  EFFECT_DEBUG_OVERBLOOM,\r\n};\r\n#else\r\nenum\r\n{\r\n  EFFECT_NONE,\r\n  EFFECT_BLOOM,\r\n  EFFECT_COUNT,\r\n  EFFECT_DEBUG_OVERBLOOM,\r\n  EFFECT_DEBUG,\r\n  EFFECT_BLOOM_RADIAL,\r\n  EFFECT_COLOR_CYCLE,\r\n  EFFECT_GLASS_CITY,\r\n};\r\n#endif \r\n\r\nstatic HDC\t\t\t        hDC;\r\nstatic HGLRC\t\t        hRC;\r\nstatic float            render_aspect;\r\nstatic float            fog_distance;\r\nstatic int              render_width;\r\nstatic int              render_height;\r\nstatic bool             letterbox;\r\nstatic int              letterbox_offset;\r\nstatic int              effect;\r\nstatic unsigned         next_fps;\r\nstatic unsigned         current_fps;\r\nstatic unsigned         frames;\r\nstatic bool             show_wireframe;\r\nstatic bool             flat;\r\nstatic bool             show_fps;\r\nstatic bool             show_fog;\r\nstatic bool             show_help;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  Draw a clock-ish progress.. widget... thing.  It's cute.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void do_progress (float center_x, float center_y, float radius, float opacity, float progress)\r\n{\r\n\r\n  int     i;\r\n  int     end_angle;\r\n  float   inner, outer;\r\n  float   angle;\r\n  float   s, c;\r\n  float   gap;\r\n\r\n  //Outer Ring\r\n  gap = radius * 0.05f;\r\n  outer = radius;\r\n  inner = radius - gap * 2;\r\n  glColor4f (1,1,1, opacity);\r\n  glBegin (GL_QUAD_STRIP);\r\n  for (i = 0; i <= 360; i+= 15) {\r\n    angle = (float)i * DEGREES_TO_RADIANS;\r\n    s = sinf (angle);\r\n    c = -cosf (angle);\r\n    glVertex2f (center_x + s * outer, center_y + c * outer);\r\n    glVertex2f (center_x + s * inner, center_y + c * inner);\r\n  }\r\n  glEnd ();\r\n  //Progress indicator\r\n  glColor4f (1,1,1, opacity);\r\n  end_angle = (int)(360 * progress);\r\n  outer = radius - gap * 3;\r\n  glBegin (GL_TRIANGLE_FAN);\r\n  glVertex2f (center_x, center_y);\r\n  for (i = 0; i <= end_angle; i+= 3) {\r\n    angle = (float)i * DEGREES_TO_RADIANS;\r\n    s = sinf (angle);\r\n    c = -cosf (angle);\r\n    glVertex2f (center_x + s * outer, center_y + c * outer);\r\n  }\r\n  glEnd ();\r\n  //Tic lines\r\n  glLineWidth (2.0f);\r\n  outer = radius - gap * 1;\r\n  inner = radius - gap * 2;\r\n  glColor4f (0,0,0, opacity);\r\n  glBegin (GL_LINES);\r\n  for (i = 0; i <= 360; i+= 15) {\r\n    angle = (float)i * DEGREES_TO_RADIANS;\r\n    s = sinf (angle);\r\n    c = -cosf (angle);\r\n    glVertex2f (center_x + s * outer, center_y + c * outer);\r\n    glVertex2f (center_x + s * inner, center_y + c * inner);\r\n  }\r\n  glEnd ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void do_effects (int type)\r\n{\r\n\r\n  float           hue1, hue2, hue3, hue4;\r\n  GLrgba          color;\r\n  float           fade;\r\n  int             radius;\r\n  int             x, y;\r\n  int             i;\r\n  int             bloom_radius;\r\n  int             bloom_step;\r\n  \r\n  fade = WorldFade ();\r\n  bloom_radius = 15;\r\n  bloom_step = bloom_radius / 3;\r\n  if (!TextureReady ())\r\n    return;\r\n  //Now change projection modes so we can render full-screen effects\r\n  glMatrixMode (GL_PROJECTION);\r\n  glPushMatrix ();\r\n  glLoadIdentity ();\r\n  glOrtho (0, render_width, render_height, 0, 0.1f, 2048);\r\n\tglMatrixMode (GL_MODELVIEW);\r\n  glPushMatrix ();\r\n  glLoadIdentity();\r\n  glTranslatef(0, 0, -1.0f);\t\t\t\t\r\n  glDisable (GL_CULL_FACE);\r\n  glDisable (GL_FOG);\r\n  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r\n  //Render full-screen effects\r\n  glBlendFunc (GL_ONE, GL_ONE);\r\n  glEnable (GL_TEXTURE_2D);\r\n  glDisable(GL_DEPTH_TEST);\r\n  glDepthMask (false);\r\n  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_BLOOM));\r\n  switch (type) {\r\n  case EFFECT_DEBUG:\r\n    glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_LOGOS));\r\n    glDisable (GL_BLEND);\r\n    glBegin (GL_QUADS);\r\n    glColor3f (1, 1, 1);\r\n    glTexCoord2f (0, 0);  glVertex2i (0, render_height / 4);\r\n    glTexCoord2f (0, 1);  glVertex2i (0, 0);\r\n    glTexCoord2f (1, 1);  glVertex2i (render_width / 4, 0);\r\n    glTexCoord2f (1, 0);  glVertex2i (render_width / 4, render_height / 4);\r\n\r\n    glTexCoord2f (0, 0);  glVertex2i (0, 512);\r\n    glTexCoord2f (0, 1);  glVertex2i (0, 0);\r\n    glTexCoord2f (1, 1);  glVertex2i (512, 0);\r\n    glTexCoord2f (1, 0);  glVertex2i (512, 512);\r\n    glEnd ();\r\n    break;\r\n  case EFFECT_BLOOM_RADIAL:\r\n    //Psychedelic bloom\r\n    glEnable (GL_BLEND);\r\n    glBegin (GL_QUADS);\r\n    color = WorldBloomColor () * BLOOM_SCALING * 2;\r\n    glColor3fv (&color.red);\r\n    for (i = 0; i <= 100; i+=10) {\r\n      glTexCoord2f (0, 0);  glVertex2i (-i, i + render_height);\r\n      glTexCoord2f (0, 1);  glVertex2i (-i, -i);\r\n      glTexCoord2f (1, 1);  glVertex2i (i + render_width, -i);\r\n      glTexCoord2f (1, 0);  glVertex2i (i + render_width, i + render_height);\r\n    }\r\n    glEnd ();\r\n    break;\r\n  case EFFECT_COLOR_CYCLE:\r\n    //Oooh. Pretty colors.  Tint the scene according to screenspace.\r\n    hue1 = (float)(GetTickCount () % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;\r\n    hue2 = (float)((GetTickCount () + COLOR_CYCLE) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;\r\n    hue3 = (float)((GetTickCount () + COLOR_CYCLE * 2) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;\r\n    hue4 = (float)((GetTickCount () + COLOR_CYCLE * 3) % COLOR_CYCLE_TIME) / COLOR_CYCLE_TIME;\r\n    glBindTexture(GL_TEXTURE_2D, 0);\r\n    glEnable (GL_BLEND);\r\n    glBlendFunc (GL_ONE, GL_ONE);\r\n    glBlendFunc (GL_DST_COLOR, GL_SRC_COLOR);\r\n    glBegin (GL_QUADS);\r\n    color = glRgbaFromHsl (hue1, 1.0f, 0.6f);\r\n    glColor3fv (&color.red);\r\n    glTexCoord2f (0, 0);  glVertex2i (0, render_height);\r\n    color = glRgbaFromHsl (hue2, 1.0f, 0.6f);\r\n    glColor3fv (&color.red);\r\n    glTexCoord2f (0, 1);  glVertex2i (0, 0);\r\n    color = glRgbaFromHsl (hue3, 1.0f, 0.6f);\r\n    glColor3fv (&color.red);\r\n    glTexCoord2f (1, 1);  glVertex2i (render_width, 0);\r\n    color = glRgbaFromHsl (hue4, 1.0f, 0.6f);\r\n    glColor3fv (&color.red);\r\n    glTexCoord2f (1, 0);  glVertex2i (render_width, render_height);\r\n    glEnd ();\r\n    break;\r\n  case EFFECT_BLOOM:\r\n    //Simple bloom effect\r\n    glBegin (GL_QUADS);\r\n    color = WorldBloomColor () * BLOOM_SCALING;\r\n    glColor3fv (&color.red);\r\n    for (x = -bloom_radius; x <= bloom_radius; x += bloom_step) {\r\n      for (y = -bloom_radius; y <= bloom_radius; y += bloom_step) {\r\n        if (abs (x) == abs (y) && x)\r\n          continue;\r\n        glTexCoord2f (0, 0);  glVertex2i (x, y + render_height);\r\n        glTexCoord2f (0, 1);  glVertex2i (x, y);\r\n        glTexCoord2f (1, 1);  glVertex2i (x + render_width, y);\r\n        glTexCoord2f (1, 0);  glVertex2i (x + render_width, y + render_height);\r\n      }\r\n    }\r\n    glEnd ();\r\n    break;\r\n  case EFFECT_DEBUG_OVERBLOOM:\r\n    //This will punish that uppity GPU. Good for testing low frame rate behavior.\r\n    glBegin (GL_QUADS);\r\n    color = WorldBloomColor () * 0.01f;\r\n    glColor3fv (&color.red);\r\n    for (x = -50; x <= 50; x+=5) {\r\n      for (y = -50; y <= 50; y+=5) {\r\n        glTexCoord2f (0, 0);  glVertex2i (x, y + render_height);\r\n        glTexCoord2f (0, 1);  glVertex2i (x, y);\r\n        glTexCoord2f (1, 1);  glVertex2i (x + render_width, y);\r\n        glTexCoord2f (1, 0);  glVertex2i (x + render_width, y + render_height);\r\n      }\r\n    }\r\n    glEnd ();\r\n    break;\r\n  }\r\n  //Do the fade to / from darkness used to hide scene transitions\r\n  if (LOADING_SCREEN) {\r\n    if (fade > 0.0f) {\r\n      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n      glEnable (GL_BLEND);\r\n      glDisable (GL_TEXTURE_2D);\r\n      glColor4f (0, 0, 0, fade);\r\n      glBegin (GL_QUADS);\r\n      glVertex2i (0, 0);\r\n      glVertex2i (0, render_height);\r\n      glVertex2i (render_width, render_height);\r\n      glVertex2i (render_width, 0);\r\n      glEnd ();\r\n    }\r\n    if (TextureReady () && !EntityReady () && fade != 0.0f) {\r\n      radius = render_width / 16;\r\n      do_progress ((float)render_width / 2, (float)render_height / 2, (float)radius, fade, EntityProgress ());\r\n      RenderPrint (render_width / 2 - LOGO_PIXELS, render_height / 2 + LOGO_PIXELS, 0, glRgba (0.5f), \"%1.2f%%\", EntityProgress () * 100.0f);\r\n      RenderPrint (1, \"%s v%d.%d.%03d\", APP_TITLE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);\r\n    }\r\n  }\r\n  glPopMatrix ();\r\n  glMatrixMode (GL_PROJECTION);\r\n  glPopMatrix ();\r\n  glMatrixMode (GL_MODELVIEW);\r\n  glEnable(GL_DEPTH_TEST);\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint RenderMaxTextureSize ()\r\n{\r\n\r\n  int mts;\r\n\r\n  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mts);\r\n  mts = MIN (mts, render_width);\r\n  return MIN (mts, render_height);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderPrint (int x, int y, int font, GLrgba color, const char *fmt, ...)\t\t\t\t\r\n{\r\n\r\n  char\t\t  text[MAX_TEXT];\t\r\n  va_list\t\tap;\t\t\t\t\t\r\n  \r\n  text[0] = 0;\r\n  if (fmt == NULL)\t\t\t\r\n\t\t  return;\t\t\t\t\t\t\r\n  va_start(ap, fmt);\t\t\r\n  vsprintf(text, fmt, ap);\t\t\t\t\r\n  va_end(ap);\t\t\r\n  glPushAttrib(GL_LIST_BIT);\t\t\t\t\r\n  glListBase(fonts[font % FONT_COUNT].base_char - 32);\t\t\t\t\r\n  glColor3fv (&color.red);\r\n\tglRasterPos2i (x, y);\r\n  glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderPrint (int line, const char *fmt, ...)\t\t\t\t\r\n{\r\n\r\n  char\t\t  text[MAX_TEXT];\t\r\n\tva_list\t\tap;\t\t\t\r\n\t\r\n  text[0] = 0;\t\r\n  if (fmt == NULL)\t\t\t\r\n\t\t  return;\t\t\t\t\t\t\r\n  va_start (ap, fmt);\t\t\r\n  vsprintf (text, fmt, ap);\t\t\t\t\r\n  va_end (ap);\t\t\r\n  glMatrixMode (GL_PROJECTION);\r\n  glPushMatrix ();\r\n  glLoadIdentity ();\r\n  glOrtho (0, render_width, render_height, 0, 0.1f, 2048);\r\n  glDisable(GL_DEPTH_TEST);\r\n  glDepthMask (false);\r\n\tglMatrixMode (GL_MODELVIEW);\r\n  glPushMatrix ();\r\n  glLoadIdentity();\r\n  glTranslatef(0, 0, -1.0f);\t\t\t\t\r\n  glDisable (GL_BLEND);\r\n  glDisable (GL_FOG);\r\n  glDisable (GL_TEXTURE_2D);\r\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  RenderPrint (0, line * FONT_SIZE - 2, 0, glRgba (0.0f), text);\r\n  RenderPrint (4, line * FONT_SIZE + 2, 0, glRgba (0.0f), text);\r\n  RenderPrint (2, line * FONT_SIZE, 0, glRgba (1.0f), text);\r\n  glPopAttrib();\t\t\t\t\t\t\r\n  glPopMatrix ();\r\n  glMatrixMode (GL_PROJECTION);\r\n  glPopMatrix ();\r\n  glMatrixMode (GL_MODELVIEW);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid static do_help (void)\r\n{\r\n\r\n  char*     text;\r\n  int       line;\r\n  char      parse[HELP_SIZE];\r\n  int       x;\r\n  \r\n  strcpy (parse, help);\r\n  line = 0;\r\n  text = strtok (parse, \"\\n\");\r\n  x = 10;\r\n  while (text) {\r\n    RenderPrint (line + 2, text);\r\n    text = strtok (NULL, \"\\n\");\r\n    line++;\r\n  }\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid do_fps ()\r\n{\r\n\r\n  LIMIT_INTERVAL (1000);\r\n  current_fps = frames;\r\n  frames = 0;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderResize (void)\t\t\r\n{\r\n\r\n  float     fovy;\r\n\r\n  render_width = WinWidth ();\r\n  render_height = WinHeight ();\r\n  if (letterbox) {\r\n    letterbox_offset = render_height / 6;\r\n    render_height = render_height - letterbox_offset * 2;\r\n  } else \r\n    letterbox_offset = 0;\r\n  //render_aspect = (float)render_height / (float)render_width;\r\n  glViewport (0, letterbox_offset, render_width, render_height);\r\n  glMatrixMode (GL_PROJECTION);\r\n  glLoadIdentity ();\r\n  render_aspect = (float)render_width / (float)render_height;\r\n  fovy = 60.0f;\r\n  if (render_aspect > 1.0f) \r\n    fovy /= render_aspect; \r\n  gluPerspective (fovy, render_aspect, 0.1f, RENDER_DISTANCE);\r\n\tglMatrixMode (GL_MODELVIEW);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderTerm (void)\r\n{\r\n\r\n  if (!hRC)\r\n    return;\r\n  wglDeleteContext (hRC);\r\n  hRC = NULL;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderInit (void)\r\n{\r\n\r\n  HWND              hWnd;\r\n\tunsigned\t\t      PixelFormat;\r\n  HFONT\t            font;\t\t\r\n\tHFONT\t            oldfont;\r\n\r\n  hWnd = WinHwnd ();\r\n  if (!(hDC = GetDC (hWnd))) \r\n\t\tYOUFAIL (\"Can't Create A GL Device Context.\") ;\r\n\tif (!(PixelFormat = ChoosePixelFormat(hDC,&pfd)))\r\n\t\tYOUFAIL (\"Can't Find A Suitable PixelFormat.\") ;\r\n  if(!SetPixelFormat(hDC,PixelFormat,&pfd))\r\n\t\tYOUFAIL (\"Can't Set The PixelFormat.\");\r\n\tif (!(hRC = wglCreateContext (hDC)))\t\r\n\t\tYOUFAIL (\"Can't Create A GL Rendering Context.\");\r\n  if(!wglMakeCurrent(hDC,hRC))\t\r\n\t\tYOUFAIL (\"Can't Activate The GL Rendering Context.\");\r\n  //Load the fonts for printing debug info to the window.\r\n  for (int i = 0; i < FONT_COUNT; i++) {\r\n\t  fonts[i].base_char = glGenLists(96); \r\n\t  font = CreateFont (FONT_SIZE,\t0, 0,\t0,\t\r\n\t\t\t\t  FW_BOLD, FALSE,\tFALSE, FALSE,\tDEFAULT_CHARSET,\tOUT_TT_PRECIS,\t\t\r\n\t\t\t\t  CLIP_DEFAULT_PRECIS,\tANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH,\r\n\t\t\t\t  fonts[i].name);\r\n\t  oldfont = (HFONT)SelectObject(hDC, font);\t\r\n\t  wglUseFontBitmaps(hDC, 32, 96, fonts[i].base_char);\r\n\t  SelectObject(hDC, oldfont);\r\n\t  DeleteObject(font);\t\t\r\n  }\r\n  //If the program is running for the first time, set the defaults.\r\n  if (!IniInt (\"SetDefaults\")) {\r\n    IniIntSet (\"SetDefaults\", 1);\r\n    IniIntSet (\"Effect\", EFFECT_BLOOM);\r\n    IniIntSet (\"ShowFog\", 1);\r\n  }\r\n  //load in our settings\r\n  letterbox = IniInt (\"Letterbox\") != 0;\r\n  show_wireframe = IniInt (\"Wireframe\") != 0;\r\n  show_fps = IniInt (\"ShowFPS\") != 0;\r\n  show_fog = IniInt (\"ShowFog\") != 0;\r\n  effect = IniInt (\"Effect\");\r\n  flat = IniInt (\"Flat\") != 0;\r\n  fog_distance = WORLD_HALF;\r\n  //clear the viewport so the user isn't looking at trash while the program starts\r\n  glViewport (0, 0, WinWidth (), WinHeight ());\r\n  glClearColor (0.0f, 0.0f, 0.0f, 1.0f);\r\n  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r\n  SwapBuffers (hDC);\r\n  RenderResize ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderFPSToggle ()\r\n{\r\n\r\n  show_fps = !show_fps;\r\n  IniIntSet (\"ShowFPS\", show_fps ? 1 : 0);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool RenderFog ()\r\n{\r\n\r\n  return show_fog;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderFogToggle ()\r\n{\r\n\r\n  show_fog = !show_fog;\r\n  IniIntSet (\"ShowFog\", show_fog ? 1 : 0);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderLetterboxToggle ()\r\n{\r\n\r\n  letterbox = !letterbox;\r\n  IniIntSet (\"Letterbox\", letterbox ? 1 : 0);\r\n  RenderResize ();\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderWireframeToggle ()\r\n{\r\n\r\n  show_wireframe = !show_wireframe;\r\n  IniIntSet (\"Wireframe\", show_wireframe ? 1 : 0);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool RenderWireframe ()\r\n{\r\n\r\n  return show_wireframe;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderEffectCycle ()\r\n{\r\n\r\n  effect = (effect + 1) % EFFECT_COUNT;\r\n  IniIntSet (\"Effect\", effect);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool RenderBloom ()\r\n{\r\n\r\n  return effect == EFFECT_BLOOM || effect == EFFECT_BLOOM_RADIAL \r\n    || effect == EFFECT_DEBUG_OVERBLOOM || effect == EFFECT_COLOR_CYCLE;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool RenderFlat ()\r\n{\r\n\r\n  return flat;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderFlatToggle ()\r\n{\r\n\r\n  flat = !flat;\r\n  IniIntSet (\"Flat\", flat ? 1 : 0);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderHelpToggle ()\r\n{\r\n\r\n  show_help = !show_help;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat RenderFogDistance ()\r\n{\r\n\r\n  return fog_distance;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This is used to set a gradient fog that goes from camera to some portion of \r\n  the normal fog distance.  This is used for making wireframe outlines and\r\n  flat surfaces fade out after rebuild.  Looks cool.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderFogFX (float scalar)\r\n{\r\n\r\n  if (scalar >= 1.0f) {\r\n    glDisable (GL_FOG);\r\n    return;\r\n  }\r\n  glFogf (GL_FOG_START, 0.0f);\r\n  glFogf (GL_FOG_END, fog_distance * 2.0f * scalar);\r\n  glEnable (GL_FOG);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid RenderUpdate (void)\t\t\r\n{\r\n\r\n  GLvector        pos;\r\n  GLvector        angle;\r\n  GLrgba          color;\r\n  int             elapsed;\r\n\r\n  frames++;\r\n  do_fps ();\r\n  glViewport (0, 0, WinWidth (), WinHeight ());\r\n  glDepthMask (true);\r\n  glClearColor (0.0f, 0.0f, 0.0f, 1.0f);\r\n  glEnable(GL_DEPTH_TEST);\r\n  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r\n  if (letterbox) \r\n    glViewport (0, letterbox_offset, render_width, render_height);\r\n  if (LOADING_SCREEN && TextureReady () && !EntityReady ()) {\r\n    do_effects (EFFECT_NONE);\r\n    SwapBuffers (hDC);\r\n    return;\r\n  }\r\n\tglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);\r\n  glShadeModel(GL_SMOOTH);\r\n  glFogi (GL_FOG_MODE, GL_LINEAR);\r\n\tglDepthFunc(GL_LEQUAL);\r\n  glEnable (GL_CULL_FACE);\r\n  glCullFace (GL_BACK);\r\n  glEnable (GL_BLEND);\r\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  glMatrixMode (GL_TEXTURE);\r\n  glLoadIdentity();\r\n\tglMatrixMode (GL_MODELVIEW);\r\n  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);\r\n  glLoadIdentity();\r\n  glLineWidth (1.0f);\r\n  pos = CameraPosition ();\r\n  angle = CameraAngle ();\r\n  glRotatef (angle.x, 1.0f, 0.0f, 0.0f);\r\n  glRotatef (angle.y, 0.0f, 1.0f, 0.0f);\r\n  glRotatef (angle.z, 0.0f, 0.0f, 1.0f);\r\n  glTranslatef (-pos.x, -pos.y, -pos.z);\r\n  glEnable (GL_TEXTURE_2D);\r\n  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r\n  //Render all the stuff in the whole entire world.\r\n  glDisable (GL_FOG);\r\n  SkyRender ();\r\n  if (show_fog) {\r\n    glEnable (GL_FOG);\r\n    glFogf (GL_FOG_START, fog_distance - 100);\r\n    glFogf (GL_FOG_END, fog_distance);\r\n    color = glRgba (0.0f);\r\n    glFogfv (GL_FOG_COLOR, &color.red);\r\n  }\r\n  WorldRender ();\r\n  if (effect == EFFECT_GLASS_CITY) {\r\n    glDisable (GL_CULL_FACE);\r\n    glEnable (GL_BLEND);\r\n    glBlendFunc (GL_ONE, GL_ONE);\r\n    glDepthFunc (false);\r\n    glDisable(GL_DEPTH_TEST);\r\n    glMatrixMode (GL_TEXTURE);\r\n    glTranslatef ((pos.x + pos.z) / SEGMENTS_PER_TEXTURE, 0, 0);\r\n\t  glMatrixMode (GL_MODELVIEW);\r\n  } else {\r\n    glEnable (GL_CULL_FACE);\r\n    glDisable (GL_BLEND);\r\n  }\r\n  EntityRender ();\r\n  if (!LOADING_SCREEN) {\r\n    elapsed = 3000 - WorldSceneElapsed ();\r\n    if (elapsed >= 0 && elapsed <= 3000) {\r\n      RenderFogFX ((float)elapsed / 3000.0f);\r\n      glDisable (GL_TEXTURE_2D);\r\n      glEnable (GL_BLEND);\r\n      glBlendFunc (GL_ONE, GL_ONE);\r\n      EntityRender ();\r\n    }\r\n  } \r\n  if (EntityReady ())\r\n    LightRender ();\r\n  CarRender ();\r\n  if (show_wireframe) {\r\n    glDisable (GL_TEXTURE_2D);\r\n    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);\r\n    EntityRender ();\r\n  }\r\n  do_effects (effect);\r\n  //Framerate tracker\r\n  if (show_fps) \r\n    RenderPrint (1, \"FPS=%d : Entities=%d : polys=%d\", current_fps, EntityCount () + LightCount () + CarCount (), EntityPolyCount () + LightCount () + CarCount ());\r\n  //Show the help overlay\r\n  if (show_help)\r\n    do_help ();\r\n  SwapBuffers (hDC);\r\n\r\n}\r\n"
  },
  {
    "path": "Render.h",
    "content": "bool  RenderBloom ();\r\nvoid  RenderEffectCycle ();\r\nbool  RenderFlat ();\r\nvoid  RenderFlatToggle ();\r\nfloat RenderFogDistance ();\r\nbool  RenderFog ();\r\nvoid  RenderFogToggle ();\r\nvoid  RenderFogFX (float scalar);\r\nvoid  RenderFPSToggle ();\r\nvoid  RenderInit ();\r\nvoid  RenderLetterboxToggle ();\r\nint   RenderMaxTextureSize ();\r\nvoid  RenderResize ();\r\nvoid  RenderTerm ();\r\nvoid  RenderUpdate ();\r\nbool  RenderWireframe ();\r\nvoid  RenderWireframeToggle ();\r\nvoid  RenderHelpToggle ();\r\nvoid  RenderPrint (int x, int y, int font, GLrgba color, const char *fmt, ...);\r\nvoid  RenderPrint (int line, const char *fmt, ...);\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"
  },
  {
    "path": "Sky.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Sky.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  Did this need to be written as a class? It did not. There will never be \r\n  more than one sky in play, so the whole class structure here is superflous,\r\n  but harmless.\r\n  \r\n-----------------------------------------------------------------------------*/\r\n\r\n#define SKYPOINTS      24\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n\r\n#include \"camera.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"sky.h\"\r\n#include \"texture.h\"\r\n#include \"glTypes.h\"\r\n#include \"world.h\"\r\n\r\nstatic CSky*          sky;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid SkyRender ()\r\n{\r\n\r\n  if (sky && !RenderFlat ())\r\n    sky->Render ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid SkyClear ()\r\n{\r\n\r\n  if(sky)\r\n    delete sky;\r\n  sky = NULL;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CSky::Render ()\r\n{\r\n\r\n  GLvector    angle, position;\r\n\r\n  if (!TextureReady ())\r\n    return;\r\n  glDepthMask (false);\r\n  glPushAttrib (GL_POLYGON_BIT | GL_FOG_BIT);\r\n  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\r\n  glDisable (GL_CULL_FACE);\r\n  glDisable (GL_FOG);\r\n  glPushMatrix ();\r\n  glLoadIdentity();\r\n  angle = CameraAngle ();\r\n  position = CameraPosition ();\r\n  glRotatef (angle.x, 1.0f, 0.0f, 0.0f);\r\n  glRotatef (angle.y, 0.0f, 1.0f, 0.0f);\r\n  glRotatef (angle.z, 0.0f, 0.0f, 1.0f);\r\n  glTranslatef (0.0f, -position.y / 100.0f, 0.0f);\r\n  glEnable (GL_TEXTURE_2D);\r\n  glBindTexture(GL_TEXTURE_2D, TextureId (TEXTURE_SKY));\r\n  glCallList (m_list);\r\n  glPopMatrix ();\r\n  glPopAttrib ();\r\n  glDepthMask (true);\r\n  glEnable (GL_COLOR_MATERIAL);\r\n\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nCSky::CSky ()\r\n{\r\n\r\n  GLvertex      circle[SKYPOINTS];\r\n  GLvector      pos;\r\n  float         angle;\r\n  int           i;\r\n  float         size;\r\n  float         rad;\r\n  float         lum;\r\n\r\n  size = 10.0f;\r\n  for (i = 0; i < SKYPOINTS; i++) {\r\n    angle = (float)i / (float)(SKYPOINTS - 1);\r\n    angle *= 360;\r\n    angle *= DEGREES_TO_RADIANS;\r\n    circle[i].position.x = sinf (angle) * size;\r\n    circle[i].position.y = 0.1f;\r\n    circle[i].position.z = cosf (angle) * size;\r\n    circle[i].uv.x = ((float)i / (float)(SKYPOINTS - 1)) * 5.0f;\r\n    circle[i].uv.y = 0.5f;\r\n    rad = ((float)i / (SKYPOINTS - 1)) * 180.0f * DEGREES_TO_RADIANS;\r\n    lum = sinf (rad);\r\n    lum = (float)pow (lum, 5);\r\n    circle[i].color = glRgba (lum);\r\n  }\r\n  m_list = glGenLists(1);\r\n  glNewList (m_list, GL_COMPILE);\r\n  glColor3f (1, 1, 1);\r\n  \r\n  glBegin (GL_QUAD_STRIP);\r\n  for (i = 0; i < SKYPOINTS; i++) {\r\n    glTexCoord2f (circle[i].uv.x, 0.0f);\r\n    glVertex3fv (&circle[i].position.x);\r\n    pos = circle[i].position;\r\n    pos.y = size / 3.5f;\r\n    glTexCoord2f (circle[i].uv.x, 1.0f);\r\n    glVertex3fv (&pos.x);\r\n  }\r\n  glEnd ();\r\n  glEndList();\t\r\n  sky = this;\r\n\r\n}"
  },
  {
    "path": "Sky.h",
    "content": "#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  GLvector      position;\r\n};\r\n\r\nclass CSky \r\n{\r\nprivate:\r\n  int                     m_list;\r\n  int                     m_stars_list;\r\n  sky_point               m_grid[SKY_GRID][SKY_GRID];\r\n\r\npublic:\r\n                          CSky ();\r\n  void                    Render (void);\r\n\r\n};\r\n\r\nvoid SkyRender ();\r\nvoid SkyClear ();\r\n"
  },
  {
    "path": "Texture.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Texture.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n  \r\n  This procedurally builds all of the textures.  \r\n\r\n  I apologize in advance for the apalling state of this module. It's the victim \r\n  of iterative and experimental development.  It has cruft, poorly named\r\n  functions, obscure code, poorly named variables, and is badly organized. Even\r\n  the formatting sucks in places. Its only saving grace is that it works.\r\n  \r\n-----------------------------------------------------------------------------*/\r\n\r\n#define RANDOM_COLOR_SHIFT  ((float)(RandomVal (10)) / 50.0f)\r\n#define RANDOM_COLOR_VAL    ((float)(RandomVal (256)) / 256.0f)\r\n#define RANDOM_COLOR_LIGHT  ((float)(200 + RandomVal (56)) / 256.0f)\r\n#define SKY_BANDS           (sizeof (sky_pos) / sizeof (int))\r\n#define PREFIX_COUNT        (sizeof (prefix) / sizeof (char*))\r\n#define SUFFIX_COUNT        (sizeof (suffix) / sizeof (char*))\r\n#define NAME_COUNT          (sizeof (name) / sizeof (char*))\r\n\r\n#include <windows.h>\r\n#include <stdio.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n#include <gl\\glu.h>\r\n#include <gl\\glaux.h>\r\n\r\n#include \"gltypes.h\"\r\n#include \"building.h\"\r\n#include \"camera.h\"\r\n#include \"car.h\"\r\n#include \"light.h\"\r\n#include \"macro.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"sky.h\"\r\n#include \"texture.h\"\r\n#include \"world.h\"\r\n#include \"win.h\"\r\n\r\nstatic char*        prefix[] = \r\n{\r\n  \"i\", \r\n  \"Green \",\r\n  \"Mega\",\r\n  \"Super \",\r\n  \"Omni\",\r\n  \"e\",\r\n  \"Hyper\",\r\n  \"Global \",\r\n  \"Vital\", \r\n  \"Next \",\r\n  \"Pacific \",\r\n  \"Metro\",\r\n  \"Unity \",\r\n  \"G-\",\r\n  \"Trans\",\r\n  \"Infinity \", \r\n  \"Superior \",\r\n  \"Monolith \",\r\n  \"Best \",\r\n  \"Atlantic \",\r\n  \"First \",\r\n  \"Union \",\r\n  \"National \",\r\n};\r\n\r\nstatic char*        name[] = \r\n{\r\n  \"Biotic\",\r\n  \"Info\",\r\n  \"Data\",\r\n  \"Solar\",\r\n  \"Aerospace\",\r\n  \"Motors\",\r\n  \"Nano\",\r\n  \"Online\",\r\n  \"Circuits\",\r\n  \"Energy\",\r\n  \"Med\",\r\n  \"Robotic\",\r\n  \"Exports\",\r\n  \"Security\",\r\n  \"Systems\",\r\n  \"Financial\",\r\n  \"Industrial\",\r\n  \"Media\",\r\n  \"Materials\",\r\n  \"Foods\",\r\n  \"Networks\",\r\n  \"Shipping\",\r\n  \"Tools\",\r\n  \"Medical\",\r\n  \"Publishing\",\r\n  \"Enterprises\",\r\n  \"Audio\",\r\n  \"Health\",\r\n  \"Bank\",\r\n  \"Imports\",\r\n  \"Apparel\",\r\n  \"Petroleum\", \r\n  \"Studios\",\r\n};\r\n\r\nstatic char*        suffix[] = \r\n{\r\n  \"Corp\",\r\n  \" Inc.\",\r\n  \"Co\",\r\n  \"World\",\r\n  \".Com\",\r\n  \" USA\",\r\n  \" Ltd.\",\r\n  \"Net\",\r\n  \" Tech\",\r\n  \" Labs\",\r\n  \" Mfg.\",\r\n  \" UK\",\r\n  \" Unlimited\",\r\n  \" One\",\r\n  \" LLC\"\r\n};\r\n  \r\nclass CTexture\r\n{\r\npublic:\r\n  int               _my_id;\r\n  unsigned          _glid;\r\n  int               _desired_size;\r\n  int               _size;\r\n  int               _half;\r\n  int               _segment_size;\r\n  bool              _ready;\r\n  bool              _masked;\r\n  bool              _mipmap;\r\n  bool              _clamp;\r\npublic:\r\n  CTexture*         _next;\r\n                    CTexture (int id, int size, bool mipmap, bool clamp, bool masked);\r\n  void              Clear () { _ready = false; }\r\n  void              Rebuild ();\r\n  void              DrawWindows ();\r\n  void              DrawSky ();\r\n  void              DrawHeadlight ();\r\n};\r\n\r\nstatic CTexture*    head;\r\nstatic bool         textures_done;\r\nstatic bool         prefix_used[PREFIX_COUNT];\r\nstatic bool         name_used[NAME_COUNT];\r\nstatic bool         suffix_used[SUFFIX_COUNT];\r\nstatic int          build_time;\r\n\r\n/*-----------------------------------------------------------------------------\r\n                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid drawrect_simple (int left, int top, int right, int bottom, GLrgba color)\r\n{\r\n\r\n  glColor3fv (&color.red);\r\n  glBegin (GL_QUADS);\r\n  glVertex2i (left, top);\r\n  glVertex2i (right, top);\r\n  glVertex2i (right, bottom);\r\n  glVertex2i (left, bottom);\r\n  glEnd ();\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid drawrect_simple (int left, int top, int right, int bottom, GLrgba color1, GLrgba color2)\r\n{\r\n\r\n  glColor3fv (&color1.red);\r\n  glBegin (GL_TRIANGLE_FAN);\r\n  glVertex2i ((left + right) / 2, (top + bottom) / 2);\r\n  glColor3fv (&color2.red);\r\n  glVertex2i (left, top);\r\n  glVertex2i (right, top);\r\n  glVertex2i (right, bottom);\r\n  glVertex2i (left, bottom);\r\n  glVertex2i (left, top);\r\n  glEnd ();\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid drawrect (int left, int top, int right, int bottom, GLrgba color)\r\n{\r\n\r\n  float     average;\r\n  float     hue;\r\n  int       potential;\r\n  int       repeats;\r\n  int       height;\r\n  int       i, j;\r\n  bool      bright;\r\n  GLrgba    color_noise;\r\n\r\n  glDisable (GL_CULL_FACE);\r\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  glEnable (GL_BLEND);\r\n  glLineWidth (1.0f);\r\n  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r\n  glColor3fv (&color.red);\r\n\r\n  if (left == right) { //in low resolution, a \"rect\" might be 1 pixel wide\r\n    glBegin (GL_LINES);\r\n    glVertex2i (left, top);\r\n    glVertex2i (left, bottom);\r\n    glEnd ();\r\n  } if (top == bottom) { //in low resolution, a \"rect\" might be 1 pixel wide\r\n    glBegin (GL_LINES);\r\n    glVertex2i (left, top);\r\n    glVertex2i (right, top);\r\n    glEnd ();\r\n  } else { // draw one of those fancy 2-dimensional rectangles\r\n    glBegin (GL_QUADS);\r\n    glVertex2i (left, top);\r\n    glVertex2i (right, top);\r\n    glVertex2i (right, bottom);\r\n    glVertex2i (left, bottom);\r\n    glEnd ();\r\n\r\n\r\n    average = (color.red + color.blue + color.green) / 3.0f;\r\n    bright = average > 0.5f;\r\n    potential = (int)(average * 255.0f);\r\n\r\n    if (bright) {\r\n      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n      glBegin (GL_POINTS);\r\n      for (i = left + 1; i < right - 1; i++) {\r\n        for (j = top + 1; j < bottom - 1; j++) {\r\n          glColor4i (255, 0, RandomVal (potential), 255);\r\n          hue = 0.2f + (float)RandomVal (100) / 300.0f + (float)RandomVal (100) / 300.0f + (float)RandomVal (100) / 300.0f;\r\n          color_noise = glRgbaFromHsl (hue, 0.3f, 0.5f);\r\n          color_noise.alpha = (float)RandomVal (potential) / 144.0f;\r\n          glColor4f (RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, RANDOM_COLOR_VAL, (float)RandomVal (potential) / 144.0f);\r\n          glColor4fv (&color_noise.red);\r\n          glVertex2i (i, j);\r\n        }\r\n      }\r\n      glEnd ();\r\n    }\r\n    repeats = RandomVal (6) + 1;\r\n    height = (bottom - top) + (RandomVal (3) - 1) + (RandomVal(3) - 1);\r\n    for (i = left; i < right; i++) {\r\n      if (RandomVal (3) == 0)\r\n        repeats = RandomVal (4) + 1;\r\n      if (RandomVal (6) == 0) {\r\n        height = bottom - top;\r\n        height = RandomVal (height);\r\n        height = RandomVal (height);\r\n        height = RandomVal (height);\r\n        height = ((bottom - top) + height) / 2;\r\n      }\r\n      for (j = 0; j < 1; j++) {\r\n        glBegin (GL_LINES);\r\n        glColor4f (0, 0, 0, (float)RandomVal (256) / 256.0f);\r\n        glVertex2i (i, bottom - height);\r\n        glColor4f (0, 0, 0, (float)RandomVal (256) / 256.0f);\r\n        glVertex2i (i, bottom);\r\n        glEnd ();\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void window (int x, int y, int size, int id, GLrgba color)\r\n{\r\n\r\n  int     margin;\r\n  int     half;\r\n  int     i;\r\n\r\n  margin = size / 3;\r\n  half = size / 2;\r\n  switch (id) {\r\n  case TEXTURE_BUILDING1: //filled, 1-pixel frame\r\n    drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);\r\n    break;\r\n  case TEXTURE_BUILDING2: //vertical\r\n    drawrect (x + margin, y + 1, x + size - margin, y + size - 1, color);\r\n    break;\r\n  case TEXTURE_BUILDING3: //side-by-side pair\r\n    drawrect (x + 1, y + 1, x + half - 1, y + size - margin, color);\r\n    drawrect (x + half + 1, y + 1, x + size - 1, y + size - margin,  color);\r\n    break;\r\n  case TEXTURE_BUILDING4: //windows with blinds\r\n    drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);\r\n    i = RandomVal (size - 2);\r\n    drawrect (x + 1, y + 1, x + size - 1, y + i + 1, color * 0.3f);\r\n\r\n    break;\r\n  case TEXTURE_BUILDING5: //vert stripes\r\n    drawrect (x + 1, y + 1, x + size - 1, y + size - 1, color);\r\n    drawrect (x + margin, y + 1, x + margin, y + size - 1, color * 0.7f);\r\n    drawrect (x + size - margin - 1, y + 1, x + size - margin - 1, y + size - 1, color * 0.3f);\r\n    break;\r\n  case TEXTURE_BUILDING6: //wide horz line\r\n    drawrect (x + 1, y + 1, x + size - 1, y + size - margin, color);\r\n    break;\r\n  case TEXTURE_BUILDING7: //4-pane\r\n    drawrect (x + 2, y + 1, x + size - 1, y + size - 1, color);\r\n    drawrect (x + 2, y + half, x + size - 1, y + half, color * 0.2f);\r\n    drawrect (x + half, y + 1, x + half, y + size - 1, color * 0.2f);\r\n    break;\r\n  case TEXTURE_BUILDING8: // Single narrow window\r\n    drawrect (x + half - 1, y + 1, x + half + 1, y + size - margin, color);\r\n    break;\r\n  case TEXTURE_BUILDING9: //horizontal\r\n    drawrect (x + 1, y + margin, x + size - 1, y + size - margin - 1, color);\r\n    break;\r\n  }\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void do_bloom (CTexture* t)\r\n{\r\n\r\n  glBindTexture(GL_TEXTURE_2D, 0);\t\t\r\n  glViewport(0, 0, t->_size , t->_size);\r\n  glCullFace (GL_BACK);\r\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  glDepthMask (true);\r\n  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r\n  glEnable(GL_DEPTH_TEST);\r\n  glEnable (GL_CULL_FACE);\r\n  glCullFace (GL_BACK);\r\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  glEnable (GL_FOG);\r\n  glFogf (GL_FOG_START, RenderFogDistance () / 2);\r\n  glFogf (GL_FOG_END, RenderFogDistance ());\r\n  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r\n  glClearColor (0.0f, 0.0f, 0.0f, 0.0f);\r\n  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r\n  glEnable (GL_TEXTURE_2D);\r\n  EntityRender ();\r\n  CarRender ();\r\n  LightRender ();\r\n  glBindTexture(GL_TEXTURE_2D, t->_glid);\t\t\r\n  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r\n\tglCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, t->_size, t->_size, 0);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nCTexture::CTexture (int id, int size, bool mipmap, bool clamp, bool masked)\r\n{\r\n\r\n  glGenTextures (1, &_glid); \r\n  _my_id = id;\r\n  _mipmap = mipmap;\r\n  _clamp = clamp;\r\n  _masked = masked;\r\n  _desired_size = size;\r\n  _size = size;\r\n  _half = size / 2;\r\n  _segment_size = size / SEGMENTS_PER_TEXTURE;\r\n  _ready = false;\r\n  _next = head;\r\n  head = this;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This draws all of the windows on a building texture. lit_density controls \r\n  how many lights are on. (1 in n chance that the light is on. Higher values \r\n  mean less lit windows. run_length controls how often it will consider \r\n  changing the lit / unlit status. 1 produces a complete scatter, higher\r\n  numbers make long strings of lights.\r\n  \r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CTexture::DrawWindows ()\r\n{\r\n\r\n\r\n  int         x, y;\r\n  int         run;\r\n  int         run_length;\r\n  int         lit_density;\r\n  GLrgba      color;\r\n  bool        lit;\r\n\r\n  //color = glRgbaUnique (_my_id);\r\n  for (y = 0; y < SEGMENTS_PER_TEXTURE; y++)  {\r\n    //Every few floors we change the behavior\r\n    if (!(y % 8)) {\r\n      run = 0;\r\n      run_length = RandomVal (9) + 2;\r\n      lit_density = 2 + RandomVal(2) + RandomVal(2);\r\n      lit = false;\r\n    }\r\n    for (x = 0; x < SEGMENTS_PER_TEXTURE; x++) {\r\n      //if this run is over reroll lit and start a new one\r\n      if (run < 1) {\r\n        run = RandomVal (run_length);\r\n        lit = RandomVal (lit_density) == 0;\r\n        //if (lit)\r\n          //color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);\r\n      }\r\n      if (lit) \r\n        color = glRgba (0.5f + (float)(RandomVal () % 128) / 256.0f) + glRgba (RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT, RANDOM_COLOR_SHIFT);\r\n       else \r\n        color = glRgba ((float)(RandomVal () % 40) / 256.0f);\r\n      window (x * _segment_size, y * _segment_size, _segment_size, _my_id, color);\r\n      run--;\r\n\r\n    }\r\n  }\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CTexture::DrawSky ()\r\n{\r\n\r\n  GLrgba          color;\r\n  float           grey;\r\n  float           scale, inv_scale;\r\n  int             i, x, y;\r\n  int             width, height;\r\n  int             offset;\r\n  int             width_adjust;\r\n  int             height_adjust;\r\n\r\n  color = WorldBloomColor ();\r\n  grey = (color.red + color.green + color.blue) / 3.0f;\r\n  //desaturate, slightly dim\r\n  color = (color + glRgba (grey) * 2.0f) / 15.0f;\r\n  glDisable (GL_BLEND);\r\n  glBegin (GL_QUAD_STRIP);\r\n  glColor3f (0,0,0);\r\n  glVertex2i (0, _half);\r\n  glVertex2i (_size, _half);\r\n  glColor3fv (&color.red);\r\n  glVertex2i (0, _size - 2);  \r\n  glVertex2i (_size, _size - 2);  \r\n  glEnd ();\r\n  //Draw a bunch of little faux-buildings on the horizon.\r\n  for (i = 0; i < _size; i += 5) \r\n    drawrect (i, _size - RandomVal (8) - RandomVal (8) - RandomVal (8), i + RandomVal (9), _size, glRgba (0.0f));\r\n  //Draw the clouds\r\n  for (i = _size - 30; i > 5; i -= 2) {\r\n\r\n    x = RandomVal (_size);\r\n    y = i;\r\n\r\n    scale = 1.0f - ((float)y / (float)_size);\r\n    width = RandomVal (_half / 2) + (int)((float)_half * scale) / 2;\r\n    scale = 1.0f - (float)y / (float)_size;\r\n    height = (int)((float)(width) * scale);\r\n    height = MAX (height, 4);\r\n\r\n    glEnable (GL_BLEND);\r\n    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n    glDisable (GL_CULL_FACE);\r\n    glEnable (GL_TEXTURE_2D);\r\n    glBindTexture (GL_TEXTURE_2D, TextureId (TEXTURE_SOFT_CIRCLE));\r\n    glDepthMask (false);\r\n    glBegin (GL_QUADS);\r\n    for (offset = -_size; offset <= _size; offset += _size) {\r\n      for (scale = 1.0f; scale > 0.0f; scale -= 0.25f) {\r\n\r\n        inv_scale = 1.0f - (scale);\r\n        if (scale < 0.4f)\r\n          color = WorldBloomColor () * 0.1f;\r\n        else\r\n          color = glRgba (0.0f);\r\n        color.alpha = 0.2f;\r\n        glColor4fv (&color.red);\r\n        width_adjust = (int)((float)width / 2.0f + (int)(inv_scale * ((float)width / 2.0f)));\r\n        height_adjust = height + (int)(scale * (float)height * 0.99f);\r\n        glTexCoord2f (0, 0);   glVertex2i (offset + x - width_adjust, y + height - height_adjust);\r\n        glTexCoord2f (0, 1);   glVertex2i (offset + x - width_adjust, y + height);\r\n        glTexCoord2f (1, 1);   glVertex2i (offset + x + width_adjust, y + height);\r\n        glTexCoord2f (1, 0);   glVertex2i (offset + x + width_adjust, y + height - height_adjust);\r\n      }\r\n\r\n    }\r\n  }\r\n  glEnd ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CTexture::DrawHeadlight ()\r\n{\r\n\r\n  float           radius;\r\n  int             i, x, y;\r\n  GLvector2       pos;\r\n\r\n  //Make a simple circle of light, bright in the center and fading out\r\n  radius = ((float)_half) - 20;\r\n  x = _half - 20;\r\n  y = _half;\r\n  glEnable (GL_BLEND);\r\n  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  glBegin (GL_TRIANGLE_FAN);\r\n  glColor4f (0.8f, 0.8f, 0.8f, 0.6f);\r\n  glVertex2i (_half - 5, y);\r\n  glColor4f (0, 0, 0, 0);\r\n  for (i = 0; i <= 360; i += 36) {\r\n    pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;\r\n    pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;\r\n    glVertex2i (x + (int)pos.x, _half + (int)pos.y);\r\n  }\r\n  glEnd ();\r\n  x = _half + 20;\r\n  glBegin (GL_TRIANGLE_FAN);\r\n  glColor4f (0.8f, 0.8f, 0.8f, 0.6f);\r\n  glVertex2i (_half + 5, y);\r\n  glColor4f (0, 0, 0, 0);\r\n  for (i = 0; i <= 360; i += 36) {\r\n    pos.x = sinf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;\r\n    pos.y = cosf ((float)(i % 360) * DEGREES_TO_RADIANS) * radius;\r\n    glVertex2i (x + (int)pos.x, _half + (int)pos.y);\r\n  }\r\n  glEnd ();\r\n  x = _half - 6;\r\n  drawrect_simple (x - 3, y - 2, x + 2, y + 2, glRgba (1.0f));\r\n  x = _half + 6;\r\n  drawrect_simple (x - 2, y - 2, x + 3, y + 2, glRgba (1.0f));\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  Here is where ALL of the procedural textures are created.  It's filled with \r\n  obscure logic, magic numbers, and messy code. Part of this is because \r\n  there is a lot of \"art\" being done here, and lots of numbers that could be \r\n  endlessly tweaked.  Also because I'm lazy.\r\n                    \r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid CTexture::Rebuild ()\r\n{\r\n\r\n  int             i, j;\r\n  int             x, y;\r\n  int             name_num, prefix_num, suffix_num;\r\n  int             max_size;\r\n  float           radius;\r\n  GLvector2       pos;\r\n  bool            use_framebuffer;\r\n  unsigned char*  bits;\r\n  unsigned        start;\r\n  int             lapsed;\r\n\r\n  start = GetTickCount ();\r\n  //Since we make textures by drawing into the viewport, we can't make them bigger \r\n  //than the current view.\r\n  _size = _desired_size;\r\n  max_size = RenderMaxTextureSize ();\r\n  while (_size > max_size)\r\n    _size /= 2;\r\n  glBindTexture(GL_TEXTURE_2D, _glid);\r\n  //Set up the texture\r\n  glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, _size, _size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);\r\n  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r\n  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r\n  if (_clamp) {\r\n    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\r\n    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\r\n  }\r\n  //Set up our viewport so that drawing into our texture will be as easy \r\n  //as possible.  We make the viewport and projection simply match the given \r\n  //texture size. \r\n  glViewport(0, 0, _size , _size);\r\n  glMatrixMode (GL_PROJECTION);\r\n  glLoadIdentity ();\r\n  glOrtho (0, _size, _size, 0, 0.1f, 2048);\r\n\tglMatrixMode (GL_MODELVIEW);\r\n  glPushMatrix ();\r\n  glLoadIdentity();\r\n  glDisable (GL_CULL_FACE);\r\n  glDisable (GL_FOG);\r\n  glBindTexture(GL_TEXTURE_2D, 0);\r\n  glTranslatef(0, 0, -10.0f);\r\n  glClearColor (0, 0, 0, _masked ? 0.0f : 1.0f);\r\n  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r\n  use_framebuffer = true;\r\n  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r\n  switch (_my_id) {\r\n  case TEXTURE_LATTICE:\r\n    glLineWidth (2.0f);\r\n\r\n    glColor3f (0,0,0);\r\n    glBegin (GL_LINES);\r\n    glVertex2i (0, 0);  glVertex2i (_size, _size);//diagonal\r\n    glVertex2i (0, 0);  glVertex2i (0, _size);//vertical\r\n    glVertex2i (0, 0);  glVertex2i (_size, 0);//vertical\r\n    glEnd ();\r\n    glBegin (GL_LINE_STRIP);\r\n    glVertex2i (0, 0);    \r\n    for (i = 0; i < _size; i += 9) {\r\n      if (i % 2)\r\n        glVertex2i (0, i);    \r\n      else\r\n        glVertex2i (i, i);    \r\n    }\r\n    for (i = 0; i < _size; i += 9) {\r\n      if (i % 2)\r\n        glVertex2i (i, 0);    \r\n      else\r\n        glVertex2i (i, i);    \r\n    }\r\n    glEnd ();\r\n    break;\r\n  case TEXTURE_SOFT_CIRCLE:\r\n    //Make a simple circle of light, bright in the center and fading out\r\n    glEnable (GL_BLEND);\r\n    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n    radius = ((float)_half) - 3;\r\n    glBegin (GL_TRIANGLE_FAN);\r\n    glColor4f (1, 1, 1, 1);\r\n    glVertex2i (_half, _half);\r\n    glColor4f (0, 0, 0, 0);\r\n    for (i = 0; i <= 360; i++) {\r\n      pos.x = sinf ((float)i * DEGREES_TO_RADIANS) * radius;\r\n      pos.y = cosf ((float)i * DEGREES_TO_RADIANS) * radius;\r\n      glVertex2i (_half + (int)pos.x, _half + (int)pos.y);\r\n    }\r\n    glEnd ();\r\n    break;\r\n  case TEXTURE_LIGHT:\r\n    glEnable (GL_BLEND);\r\n    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n    radius = ((float)_half) - 3;\r\n    for (j = 0; j < 2; j++) {\r\n      glBegin (GL_TRIANGLE_FAN);\r\n      glColor4f (1, 1, 1, 1);\r\n      glVertex2i (_half, _half);\r\n      if (!j)\r\n        radius = ((float)_half / 2);\r\n      else\r\n        radius = 8;\r\n      glColor4f (1, 1, 1, 0);\r\n      for (i = 0; i <= 360; i++) {\r\n        pos.x = sinf ((float)i * DEGREES_TO_RADIANS) * radius;\r\n        pos.y = cosf ((float)i * DEGREES_TO_RADIANS) * radius;\r\n        glVertex2i (_half + (int)pos.x, _half + (int)pos.y);\r\n      }\r\n      glEnd ();\r\n    }\r\n    break;\r\n  case TEXTURE_HEADLIGHT:\r\n    DrawHeadlight ();\r\n    break;\r\n  case TEXTURE_LOGOS:\r\n    i = 0;\r\n    glDepthMask (false);\r\n    glDisable (GL_BLEND);\r\n    name_num = RandomVal (NAME_COUNT);\r\n    prefix_num = RandomVal (PREFIX_COUNT);\r\n    suffix_num = RandomVal (SUFFIX_COUNT);\r\n    glColor3f (1,1,1);\r\n    while (i < _size) {\r\n      //randomly use a prefix OR suffix, but not both.  Too verbose.\r\n      if (COIN_FLIP)\r\n        RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), \"%s%s\", prefix[prefix_num], name[name_num]);\r\n      else\r\n        RenderPrint (2, _size - i - LOGO_PIXELS / 4, RandomVal(), glRgba (1.0f), \"%s%s\", name[name_num], suffix[suffix_num]);\r\n      name_num = (name_num + 1) % NAME_COUNT;\r\n      prefix_num = (prefix_num + 1) % PREFIX_COUNT;\r\n      suffix_num = (suffix_num + 1) % SUFFIX_COUNT;\r\n      i += LOGO_PIXELS;\r\n    }\r\n    break;\r\n  case TEXTURE_TRIM:\r\n    int     margin;\r\n    y = 0;\r\n    margin = MAX (TRIM_PIXELS / 4, 1);\r\n    for (x = 0; x < _size; x += TRIM_PIXELS) \r\n      drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));\r\n    y += TRIM_PIXELS;\r\n    for (x = 0; x < _size; x += TRIM_PIXELS * 2) \r\n      drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));\r\n    y += TRIM_PIXELS;\r\n    for (x = 0; x < _size; x += TRIM_PIXELS * 3) \r\n      drawrect_simple (x + margin, y + margin, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));\r\n    y += TRIM_PIXELS;\r\n    for (x = 0; x < _size; x += TRIM_PIXELS) \r\n      drawrect_simple (x + margin, y + margin * 2, x + TRIM_PIXELS - margin, y + TRIM_PIXELS - margin, glRgba (1.0f), glRgba (0.5f));\r\n    break;\r\n  case TEXTURE_SKY:\r\n    DrawSky ();\r\n    break;\r\n  default: //building textures\r\n    DrawWindows ();\r\n    break;\r\n  }\r\n  glPopMatrix ();\r\n  //Now blit the finished image into our texture  \r\n  if (use_framebuffer) {\r\n    glBindTexture(GL_TEXTURE_2D, _glid);\t\t\r\n\t  glCopyTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, _size, _size, 0);\r\n  }\r\n  if (_mipmap) {\r\n    bits = (unsigned char*)malloc (_size * _size * 4);\r\n    glGetTexImage (GL_TEXTURE_2D,\t0, GL_RGBA, GL_UNSIGNED_BYTE, bits);\r\n    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, _size, _size, GL_RGBA, GL_UNSIGNED_BYTE, bits);\r\n    free (bits);\r\n\t  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);\r\n\t  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);\r\n  } else\r\n    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);\r\n  //cleanup and restore the viewport\r\n  RenderResize ();  \r\n  _ready = true;\r\n  lapsed = GetTickCount () - start;\r\n  build_time += lapsed;\r\n    \r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nunsigned TextureId (int id)\r\n{\r\n\r\n  for (CTexture* t = head; t; t = t->_next) {\r\n    if (t->_my_id == id)\r\n      return t->_glid;\r\n  }\r\n  return 0;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nunsigned TextureRandomBuilding (int index)\r\n{\r\n\r\n  index = abs (index) % BUILDING_COUNT;\r\n  return TextureId (TEXTURE_BUILDING1 + index);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid TextureReset (void)\r\n{\r\n\r\n  textures_done = false;\r\n  build_time = 0;\r\n  for (CTexture* t = head; t; t = t->_next)\r\n    t->Clear ();\r\n  ZeroMemory (prefix_used, sizeof (prefix_used));\r\n  ZeroMemory (name_used, sizeof (name_used));\r\n  ZeroMemory (suffix_used, sizeof (suffix_used));\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool TextureReady ()\r\n{\r\n\r\n  return textures_done;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid TextureUpdate (void)\r\n{\r\n\r\n  if (textures_done) {\r\n    if (!RenderBloom ())\r\n      return;\r\n    CTexture*   t;\r\n\r\n    for (t = head; t; t = t->_next) {\r\n      if (t->_my_id != TEXTURE_BLOOM) \r\n        continue;\r\n      do_bloom (t);\r\n      return;\r\n    }\r\n  }\r\n  for (CTexture* t = head; t; t = t->_next) {\r\n    if (!t->_ready) {\r\n      t->Rebuild();\r\n      return;\r\n    }\r\n  } \r\n  textures_done = true;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid TextureTerm (void)\r\n{\r\n\r\n  CTexture*    t;\r\n\r\n  while (head) {\r\n    t = head->_next;\r\n    free (head);\r\n    head = t;\r\n  }\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid TextureInit (void)\r\n{\r\n\r\n  new CTexture (TEXTURE_SKY,          512,  true,  false, false);\r\n  new CTexture (TEXTURE_LATTICE,      128,  true,  true,  true);\r\n  new CTexture (TEXTURE_LIGHT,        128,  false, false, true);\r\n  new CTexture (TEXTURE_SOFT_CIRCLE,  128,  false, false, true);\r\n  new CTexture (TEXTURE_HEADLIGHT,    128,  false, false, true);\r\n  new CTexture (TEXTURE_TRIM,  TRIM_RESOLUTION,  true, false, false);\r\n  new CTexture (TEXTURE_LOGOS, LOGO_RESOLUTION,  true, false, true);\r\n  for (int i = TEXTURE_BUILDING1; i <= TEXTURE_BUILDING9; i++)\r\n    new CTexture (i, 512, true, false, false);\r\n  new CTexture (TEXTURE_BLOOM,  512,  true, false, false);\r\n  int  names = PREFIX_COUNT * NAME_COUNT + SUFFIX_COUNT * NAME_COUNT;\r\n\r\n}\r\n"
  },
  {
    "path": "Texture.h",
    "content": "#define SEGMENTS_PER_TEXTURE  64\r\n#define ONE_SEGMENT           (1.0f / SEGMENTS_PER_TEXTURE)\r\n#define LANES_PER_TEXTURE     8\r\n#define LANE_SIZE             (1.0f / LANES_PER_TEXTURE)\r\n#define LANE_PIXELS           (_size / LANES_PER_TEXTURE)\r\n#define TRIM_RESOLUTION       256\r\n#define TRIM_ROWS             4\r\n#define TRIM_SIZE             (1.0f / TRIM_ROWS)\r\n#define TRIM_PIXELS           (TRIM_RESOLUTION / TRIM_ROWS)\r\n#define LOGO_RESOLUTION       512\r\n#define LOGO_ROWS             16\r\n#define LOGO_SIZE             (1.0f / LOGO_ROWS)\r\n#define LOGO_PIXELS           (LOGO_RESOLUTION / LOGO_ROWS)\r\n\r\nenum\r\n{\r\n  TEXTURE_LIGHT,\r\n  TEXTURE_SOFT_CIRCLE,\r\n  TEXTURE_SKY,\r\n  TEXTURE_LOGOS,\r\n  TEXTURE_TRIM,\r\n  TEXTURE_BLOOM,\r\n  TEXTURE_HEADLIGHT,\r\n  TEXTURE_LATTICE,\r\n  TEXTURE_BUILDING1,\r\n  TEXTURE_BUILDING2,\r\n  TEXTURE_BUILDING3,\r\n  TEXTURE_BUILDING4,\r\n  TEXTURE_BUILDING5,\r\n  TEXTURE_BUILDING6,\r\n  TEXTURE_BUILDING7,\r\n  TEXTURE_BUILDING8,\r\n  TEXTURE_BUILDING9,\r\n  TEXTURE_COUNT,\r\n};\r\n\r\n#define BUILDING_COUNT    ((TEXTURE_BUILDING9 - TEXTURE_BUILDING1) + 1)\r\n\r\nunsigned  TextureFromName (char* name);\r\nunsigned  TextureId (int id);\r\nvoid      TextureInit (void);\r\nvoid      TextureTerm (void);\r\nunsigned  TextureRandomBuilding (int index);\r\nbool      TextureReady ();\r\nvoid      TextureReset (void);\r\nvoid      TextureUpdate (void);\r\n\r\n"
  },
  {
    "path": "Visible.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Visible.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This module runs the visibility grid, a 2-dimensional array that aids in\r\n  culling objects during rendering. \r\n\r\n  There are many ways this could be refined or sped up, although tests indicate\r\n  it's not a huge drain on performance.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n\r\n#include \"glTypes.h\"\r\n#include \"camera.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"visible.h\"\r\n#include \"world.h\"\r\n#include \"win.h\"\r\n\r\nstatic bool          vis_grid[GRID_SIZE][GRID_SIZE];\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool Visible (GLvector pos)\r\n{\r\n\r\n  return vis_grid[WORLD_TO_GRID(pos.x)][WORLD_TO_GRID(pos.z)];\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool Visible (int x, int z)\r\n{\r\n\r\n  return vis_grid[x][z];\r\n\r\n}\r\n\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid VisibleUpdate (void)\r\n{\r\n\r\n  GLvector  angle;\r\n  GLvector  position;\r\n  int       x, y, grid_x, grid_z;\r\n  int       left, right, front, back;\r\n  float     angle_to;\r\n  float     angle_diff;\r\n  float     target_x, target_z;\r\n\r\n  //Clear the visibility table\r\n  ZeroMemory (vis_grid, sizeof (vis_grid));\r\n  //Calculate which cell the camera is in\r\n  angle = CameraAngle ();\r\n  position = CameraPosition ();\r\n  grid_x = WORLD_TO_GRID(position.x);\r\n  grid_z = WORLD_TO_GRID(position.z);\r\n  //Cells directly adjactent to the camera might technically fall out of the fov,\r\n  //but still have a few objects poking into screenspace when looking up or down.\r\n  //Rather than obsess over sorting those objects properly, it's more efficient to\r\n  //just mark them visible.\r\n  left = right = front = back = 3;\r\n  //Looking north, can't see south.\r\n  if (angle.y < 45.0f || angle.y > 315.0f)\r\n    front = 0;\r\n  //Looking south, can't see north\r\n  if (angle.y > 135.0f && angle.y < 225.0f)\r\n    back = 0;\r\n  //Looking east, can't see west\r\n  if (angle.y > 45.0f && angle.y < 135.0f)\r\n    left = 0;\r\n  //Looking west, can't see east\r\n  if (angle.y > 225.0f && angle.y < 315.0f)\r\n    right = 0;\r\n  //Now mark the block around us the might be visible\r\n  for (x = grid_x - left; x <= grid_x + right; x++) {\r\n    if (x < 0 || x >= GRID_SIZE) //just in case the camera leaves the world map\r\n      continue;\r\n    for (y = grid_z - back; y <= grid_z + front; y++) {\r\n      if (y < 0 || y >= GRID_SIZE) //just in case the camera leaves the world map\r\n        continue;\r\n      vis_grid[x][y] = true;\r\n    }\r\n  }\r\n  //Doesn't matter where we are facing, objects in current cell are always visible\r\n  vis_grid[grid_x][grid_z] = true;\r\n  //Here, we look at the angle from the current camera position to the cell \r\n  //on the grid, and how much that angle deviates from the current view angle. \r\n  for (x = 0; x < GRID_SIZE; x++) {\r\n    for (y = 0; y < GRID_SIZE; y++) {\r\n      //if we marked it visible earlier, skip all this math\r\n      if (vis_grid[x][y])\r\n        continue;\r\n      //if the camera is to the left of this cell, use the left edge\r\n      if (grid_x < x) \r\n        target_x = (float)x * GRID_RESOLUTION;\r\n      else \r\n        target_x = (float)(x + 1) * GRID_RESOLUTION;\r\n      if (grid_z < y) \r\n        target_z = (float)y * GRID_RESOLUTION;\r\n      else\r\n        target_z = (float)(y + 1) * GRID_RESOLUTION;\r\n      angle_to = 180 - MathAngle (target_x, target_z, position.x, position.z);\r\n      //Store how many degrees the cell is to the \r\n      angle_diff = (float)fabs (MathAngleDifference (angle.y, angle_to));\r\n      vis_grid[x][y] = angle_diff < 45;\r\n    }\r\n  }\r\n\r\n\r\n}\r\n  \r\n"
  },
  {
    "path": "Visible.h",
    "content": "#define GRID_RESOLUTION   32\r\n#define GRID_CELL         (GRID_RESOLUTION / 2)\r\n#define GRID_SIZE         (WORLD_SIZE / GRID_RESOLUTION)\r\n#define WORLD_TO_GRID(x)  (int)(x / GRID_RESOLUTION)\r\n#define GRID_TO_WORLD(x)  ((float)x * GRID_RESOLUTION)\r\n\r\n\r\n\r\nvoid VisibleUpdate (void);\r\nbool Visible (GLvector pos);\r\nbool Visible (int x, int z);\r\n"
  },
  {
    "path": "Win.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Win.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  Create the main window and make it go.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define MOUSE_MOVEMENT          0.5f\r\n\r\n#include <windows.h>\r\n#include <math.h>\r\n#include <stdarg.h>\r\n#include <string.h>\r\n#include <stdio.h>\r\n#include <time.h>\r\n#include <scrnsave.h>\r\n\r\n#include \"camera.h\"\r\n#include \"car.h\"\r\n#include \"entity.h\"\r\n#include \"glTypes.h\"\r\n#include \"ini.h\"\r\n#include \"macro.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"texture.h\"\r\n#include \"win.h\"\r\n#include \"world.h\"\r\n#include \"visible.h\"\r\n\r\n#pragma comment (lib, \"opengl32.lib\")\r\n#pragma comment (lib, \"winmm.lib\")\r\n#pragma comment (lib, \"glu32.lib\")\r\n#if SCREENSAVER\r\n#pragma comment (lib, \"scrnsave.lib\")\r\n#endif\t\r\n\r\n\r\n\r\nstatic HWND         hwnd;\r\nstatic HINSTANCE    module;\r\nstatic int          width;\r\nstatic int          height;\r\nstatic int          half_width;\r\nstatic int          half_height;\r\nstatic bool         lmb;\r\nstatic bool         rmb;\r\nstatic bool         mouse_forced;\r\nstatic POINT        select_pos;\r\nstatic POINT        mouse_pos;\r\nstatic bool         quit;\r\nstatic HINSTANCE    instance;\r\n\r\nLONG WINAPI ScreenSaverProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void CenterCursor ()\r\n{\r\n\r\n  int             center_x;\r\n  int             center_y;\r\n  RECT            rect;\r\n\r\n  SetCursor (NULL);\r\n  mouse_forced = true;\r\n  GetWindowRect (hwnd, &rect);\r\n  center_x = rect.left + (rect.right - rect.left) / 2;\r\n  center_y = rect.top + (rect.bottom - rect.top) / 2;\r\n  SetCursorPos (center_x, center_y);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void MoveCursor (int x, int y)\r\n{\r\n\r\n  int             center_x;\r\n  int             center_y;\r\n  RECT            rect;\r\n\r\n  SetCursor (NULL);\r\n  mouse_forced = true;\r\n  GetWindowRect (hwnd, &rect);\r\n  center_x = rect.left + x;\r\n  center_y = rect.top + y;\r\n  SetCursorPos (center_x, center_y);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                                    n o t e\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WinPopup (char* message, ...)\r\n{\r\n\r\n  va_list  \t\tmarker;\r\n  char        buf[1024];\r\n\r\n  va_start (marker, message);\r\n  vsprintf (buf, message, marker); \r\n  va_end (marker);\r\n  MessageBox (NULL, buf, APP_TITLE, MB_ICONSTOP | MB_OK | \r\n    MB_TASKMODAL);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint WinWidth (void)\r\n{\r\n\r\n  return width;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WinMousePosition (int* x, int* y)\r\n{\r\n\r\n  *x = select_pos.x;\r\n  *y = select_pos.y;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint WinHeight (void)\r\n{\r\n\r\n  return height;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WinTerm (void)\r\n{\r\n#if !SCREENAVER\r\n  DestroyWindow (hwnd);\r\n#endif\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nHWND WinHwnd (void)\r\n{\r\n\r\n  return hwnd;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid AppQuit ()\r\n{\r\n\r\n  quit = true;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid AppUpdate ()\r\n{\r\n\r\n  CameraUpdate ();\r\n  EntityUpdate ();\r\n  WorldUpdate ();\r\n  TextureUpdate ();\r\n  VisibleUpdate ();\r\n  CarUpdate ();\r\n  RenderUpdate ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid AppInit (void)\r\n{\r\n\r\n  RandomInit (time (NULL));\r\n  CameraInit ();\r\n  RenderInit ();\r\n  TextureInit ();\r\n  WorldInit ();\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n                                W i n M a i n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid AppTerm (void) \r\n{\r\n\r\n  TextureTerm ();\r\n  WorldTerm ();\r\n  RenderTerm ();\r\n  CameraTerm ();\r\n  WinTerm ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                                W i n M a i n\r\n-----------------------------------------------------------------------------*/\r\n#if !SCREENSAVER\r\n\r\nint PASCAL WinMain (HINSTANCE instance_in, HINSTANCE previous_instance,\r\n  LPSTR command_line, int show_style)\r\n{\r\n\r\n \tMSG\t\t  msg;\r\n\r\n  instance = instance_in;\r\n  WinInit ();\r\n  AppInit ();\r\n  while (!quit) {\r\n\t\tif (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))\t{\r\n\t\t\tif (msg.message == WM_QUIT)\t\r\n\t\t\t\tquit = true;\r\n\t\t\telse {\r\n\t\t\t\tTranslateMessage(&msg);\t\t\t\r\n\t\t\t\tDispatchMessage(&msg);\t\t\t\r\n\t\t\t}\r\n    } else \r\n      AppUpdate ();\r\n\r\n  }\r\n  AppTerm ();\r\n  return 0;\r\n\r\n}\r\n\r\n#else\r\n\r\nBOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { return FALSE; }\r\nBOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; }\r\n\r\n#endif\r\n\r\nLONG WINAPI ScreenSaverProc(HWND hwnd_in,UINT message,WPARAM wparam,LPARAM lparam)\r\n{\r\n\r\n  RECT            r;\r\n  int             key;\r\n  float           delta_x, delta_y;\r\n  POINT           p;\r\n\r\n  // Handles screen saver messages\r\n  switch(message)\r\n  {\r\n  case WM_SIZE:\r\n    width = LOWORD(lparam);  // width of client area \r\n    height = HIWORD(lparam); // height of client area \r\n    if (wparam == SIZE_MAXIMIZED) {\r\n      IniIntSet (\"WindowMaximized\", 1);\r\n    } else {\r\n      IniIntSet (\"WindowWidth\", width);\r\n      IniIntSet (\"WindowHeight\", height);\r\n      IniIntSet (\"WindowMaximized\", 0);\r\n    }\r\n    RenderResize ();\r\n    break;\r\n  case WM_KEYDOWN:\r\n    key = (int) wparam; \r\n    if (key == 'R')\r\n      WorldReset (); \r\n    else if (key == 'W')\r\n      RenderWireframeToggle ();\r\n    else if (key == 'E')\r\n      RenderEffectCycle ();\r\n    else if (key == 'L')\r\n      RenderLetterboxToggle ();\r\n    else if (key == 'F')\r\n      RenderFPSToggle ();\r\n    else if (key == 'G')\r\n      RenderFogToggle ();\r\n    else if (key == 'T')\r\n      RenderFlatToggle ();\r\n    else if (key == VK_F1)\r\n      RenderHelpToggle ();\r\n    else if (key == VK_ESCAPE)\r\n      break;\r\n    else if (!SCREENSAVER) {\r\n      //Dev mode keys\r\n      if (key == 'C')\r\n        CameraAutoToggle (); \r\n      if (key == 'B')\r\n        CameraNextBehavior ();\r\n      if (key == VK_F5)\r\n        CameraReset ();\r\n      if (key == VK_UP)\r\n        CameraMedial (1.0f);\r\n      if (key == VK_DOWN)\r\n        CameraMedial (-1.0f);\r\n      if (key == VK_LEFT)\r\n        CameraLateral (1.0f);\r\n      if (key == VK_RIGHT)\r\n        CameraLateral (-1.0f);\r\n      if (key == VK_PRIOR)\r\n        CameraVertical (1.0f);\r\n      if (key == VK_NEXT)\r\n        CameraVertical (-1.0f);\r\n      if (key == VK_F5)\r\n        CameraReset ();\r\n      return 0;\r\n    } else\r\n      break;\r\n    return 0;\r\n  case WM_MOVE:\r\n    GetClientRect (hwnd, &r);\r\n    height = r.bottom - r.top;\r\n    width = r.right - r.left;\r\n    IniIntSet (\"WindowX\", r.left);\r\n    IniIntSet (\"WindowY\", r.top);\r\n    IniIntSet (\"WindowWidth\", width);\r\n    IniIntSet (\"WindowHeight\", height);\r\n    half_width = width / 2;\r\n    half_height = height / 2;\r\n    return 0;\r\n  case WM_LBUTTONDOWN:\r\n    lmb = true;\r\n    SetCapture (hwnd);\r\n    break;\r\n  case WM_RBUTTONDOWN:\r\n    rmb = true;\r\n    SetCapture (hwnd);\r\n    break;\r\n  case WM_LBUTTONUP:\r\n    lmb = false;\r\n    if (!rmb) {\r\n      ReleaseCapture ();\r\n      MoveCursor (select_pos.x, select_pos.y);\r\n    }\r\n    break;\r\n  case WM_RBUTTONUP:\r\n    rmb = false;\r\n    if (!lmb) {\r\n      ReleaseCapture ();\r\n      MoveCursor (select_pos.x, select_pos.y);\r\n    }\r\n    break;\r\n  case WM_MOUSEMOVE:\r\n    p.x = LOWORD(lparam);  // horizontal position of cursor \r\n    p.y = HIWORD(lparam);  // vertical position of cursor \r\n    if (p.x < 0 || p.x > width)\r\n      break;\r\n    if (p.y < 0 || p.y > height)\r\n      break;\r\n    if (!mouse_forced && !lmb && !rmb) {\r\n      select_pos = p; \r\n    }\r\n    if (mouse_forced) {\r\n      mouse_forced = false;\r\n    } else if (rmb || lmb) {\r\n      CenterCursor ();\r\n      delta_x = (float)(mouse_pos.x - p.x) * MOUSE_MOVEMENT;\r\n      delta_y = (float)(mouse_pos.y - p.y) * MOUSE_MOVEMENT;\r\n      if (rmb && lmb) {\r\n        GLvector    pos;\r\n        CameraPan (delta_x);\r\n        pos = CameraPosition ();\r\n        pos.y += delta_y;\r\n        CameraPositionSet (pos);\r\n      } else if (rmb) {\r\n        CameraPan (delta_x);\r\n        CameraForward (delta_y);\r\n      } else if (lmb) {\r\n        GLvector    angle;\r\n        angle = CameraAngle ();\r\n        angle.y -= delta_x;\r\n        angle.x += delta_y;\r\n        CameraAngleSet (angle);\r\n      }\r\n    }\r\n    mouse_pos = p;\r\n    break;\r\n  case WM_CREATE:\r\n    hwnd = hwnd_in;\r\n    if (SCREENSAVER)\r\n      AppInit ();\r\n    SetTimer (hwnd, 1, 7, NULL); \r\n    return 0;\r\n  case WM_TIMER:\r\n    AppUpdate ();\r\n    return 0;\r\n  case WM_DESTROY:\r\n    PostQuitMessage(0);\r\n    return 0;\r\n  }\r\n#if SCREENSAVER\r\n  return DefScreenSaverProc(hwnd_in,message,wparam,lparam);\r\n#else\r\n  return DefWindowProc (hwnd_in,message,wparam,lparam);   \r\n#endif\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool WinInit (void)\r\n{\r\n\r\n  WNDCLASSEX    wcex;\r\n  int           x, y;\r\n  int           style;\r\n  bool          max;\r\n\r\n\twcex.cbSize         = sizeof(WNDCLASSEX); \r\n\twcex.style\t\t\t    = CS_HREDRAW | CS_VREDRAW;\r\n\twcex.lpfnWndProc\t  = (WNDPROC)ScreenSaverProc;\r\n\twcex.cbClsExtra\t\t  = 0;\r\n\twcex.cbWndExtra\t\t  = 0;\r\n\twcex.hInstance\t\t  = instance;\r\n\twcex.hIcon\t\t\t    = NULL;\r\n\twcex.hCursor\t\t    = LoadCursor(NULL, IDC_ARROW);\r\n\twcex.hbrBackground\t= (HBRUSH)(COLOR_BTNFACE+1);\r\n\twcex.lpszMenuName\t  = NULL;\r\n\twcex.lpszClassName\t= APP_TITLE;\r\n\twcex.hIconSm\t\t    = NULL;\r\n  if (!RegisterClassEx(&wcex)) {\r\n    WinPopup (\"Cannot create window class\");\r\n    return false;\r\n  }\r\n  x = IniInt (\"WindowX\");\r\n  y = IniInt (\"WindowY\");\r\n  style = WS_TILEDWINDOW;\r\n  style |= WS_MAXIMIZE;\r\n  width = IniInt (\"WindowWidth\");\r\n  height = IniInt (\"WindowHeight\");\r\n  width = CLAMP (width, 800, 2048);\r\n  height = CLAMP (height, 600, 2048);\r\n  half_width = width / 2;\r\n  half_height = height / 2;\r\n  max = IniInt (\"WindowMaximized\") == 1;\r\n  if (!(hwnd = CreateWindowEx (0, APP_TITLE, APP_TITLE, style,\r\n    CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, instance, NULL))) {\r\n    WinPopup (\"Cannot create window\");\r\n    return false;\r\n  }\r\n  if (max) \r\n    ShowWindow (hwnd, SW_MAXIMIZE);\r\n  else\r\n    ShowWindow (hwnd, SW_SHOW);\r\n  UpdateWindow (hwnd);\r\n  return true;\r\n\r\n}"
  },
  {
    "path": "Win.h",
    "content": "//Versioning info\r\n#define APP_TITLE           \"PixelCity\"\r\n#define APP                 \"pixelcity\"\r\n#define VERSION_MAJOR       1\r\n#define VERSION_MINOR       0\r\n#define VERSION_REVISION    10\r\n//Best to disable screensaver mode when working on the program.\r\n#define SCREENSAVER         0\r\n//Do we hide scene building behing a loading screen or show it?\r\n#define LOADING_SCREEN      1\r\n//Controls the density of cars.\r\n#define CARS                500\r\n//The \"dead zone\" along the edge of the world, with super-low detail.\r\n#define WORLD_EDGE          200\r\n//How often to rebuild the city\r\n#define RESET_INTERVAL      (SCREENSAVER ? 120000 : 999999)//milliseconds\r\n//How long the screen fade takes when transitioning to a new city\r\n#define FADE_TIME           (SCREENSAVER ? 1500 : 1) //milliseconds\r\n//Debug ground texture that shows traffic lanes\r\n#define SHOW_DEBUG_GROUND   0\r\n//Controls the ammount of space available for buildings.  \r\n//Other code is wrtten assuming this will be a power of two.\r\n#define WORLD_SIZE          1024\r\n#define WORLD_HALF          (WORLD_SIZE / 2)\r\n//Bitflags used to track how world space is being used.\r\n#define CLAIM_ROAD          1\r\n#define CLAIM_WALK          2\r\n#define CLAIM_BUILDING      4\r\n#define MAP_ROAD_NORTH      8\r\n#define MAP_ROAD_SOUTH      16\r\n#define MAP_ROAD_EAST       32\r\n#define MAP_ROAD_WEST       64\r\n//Random SATURATED color\r\n#define RANDOM_COLOR          (glRgbaFromHsl ((float)RandomVal (255)/255,1.0f, 0.75f))\r\n//Used in orienting roads and cars\r\nenum\r\n{\r\n  NORTH,\r\n  EAST,\r\n  SOUTH,\r\n  WEST\r\n};\r\n\r\nHWND  WinHwnd (void);\r\nvoid  WinPopup (char* message, ...);\r\nvoid  WinTerm (void);\r\nbool  WinInit (void);\r\nint   WinWidth (void);\r\nint   WinHeight (void);\r\nvoid  WinMousePosition (int* x, int* y);"
  },
  {
    "path": "World.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  World.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  This holds a bunch of variables used by the other modules. It has the \r\n  claim system, which tracks all of the \"property\" is being used: As roads,\r\n  buildings, etc. \r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define HUE_COUNT         (sizeof(hue_list)/sizeof(float))\r\n#define LIGHT_COLOR_COUNT (sizeof(light_colors)/sizeof(HSL))\r\n\r\n#include <windows.h>\r\n#include <gl\\gl.h>\r\n#include <gl\\glu.h>\r\n#include <gl\\glaux.h>\r\n#include <math.h>\r\n#include <time.h>\r\n#include <vector>\r\n\r\n#include \"glTypes.h\"\r\n#include \"building.h\"\r\n#include \"car.h\"\r\n#include \"deco.h\"\r\n#include \"camera.h\"\r\n#include \"light.h\"\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"mesh.h\"\r\n#include \"random.h\"\r\n#include \"render.h\"\r\n#include \"sky.h\"\r\n#include \"texture.h\"\r\n#include \"visible.h\"\r\n#include \"win.h\"\r\n#include \"world.h\"\r\n\r\nusing namespace std;\r\n\r\nstruct plot\r\n{\r\n  int             x;\r\n  int             z;\r\n  int             width;\r\n  int             depth;\r\n\r\n};\r\n\r\nenum {\r\n  FADE_IDLE,\r\n  FADE_OUT,\r\n  FADE_WAIT,\r\n  FADE_IN,\r\n};\r\n\r\nstruct HSL\r\n{\r\n  float     hue;\r\n  float     sat;\r\n  float     lum;\r\n};\r\n\r\nclass CStreet\r\n{\r\npublic:\r\n  int                 _x;\r\n  int                 _y;\r\n  int                 _width;\r\n  int                 _depth;\r\n  CMesh*              _mesh;\r\n  \r\n  CStreet (int x, int y, int width, int depth);\r\n  ~CStreet();\r\n  void                Render ();\r\n\r\n};\r\n\r\nstatic HSL            light_colors[] = \r\n{ \r\n  0.04f,  0.9f,  0.93f,   //Amber / pink\r\n  0.055f, 0.95f, 0.93f,   //Slightly brighter amber \r\n  0.08f,  0.7f,  0.93f,   //Very pale amber\r\n  0.07f,  0.9f,  0.93f,   //Very pale orange\r\n  0.1f,   0.9f,  0.85f,   //Peach\r\n  0.13f,  0.9f,  0.93f,   //Pale Yellow\r\n  0.15f,  0.9f,  0.93f,   //Yellow\r\n  0.17f,  1.0f,  0.85f,   //Saturated Yellow\r\n  0.55f,  0.9f,  0.93f,   //Cyan\r\n  0.55f,  0.9f,  0.93f,   //Cyan - pale, almost white\r\n  0.6f,   0.9f,  0.93f,   //Pale blue\r\n  0.65f,  0.9f,  0.93f,   //Pale Blue II, The Palening\r\n  0.65f,  0.4f,  0.99f,   //Pure white. Bo-ring.\r\n  0.65f,  0.0f,  0.8f,    //Dimmer white.\r\n  0.65f,  0.0f,  0.6f,    //Dimmest white.\r\n}; \r\n\r\nstatic float          hue_list[] = { 0.04f, 0.07f, 0.1f, 0.5f, 0.6f }; //Yellows and blues - good for lights\r\nstatic GLrgba         bloom_color;\r\nstatic long           last_update;\r\nstatic char           world[WORLD_SIZE][WORLD_SIZE];\r\nstatic CSky*          sky;\r\nstatic int            fade_state;\r\nstatic unsigned       fade_start;\r\nstatic float          fade_current;\r\nstatic int            modern_count;\r\nstatic int            tower_count;\r\nstatic int            blocky_count;\r\nstatic bool           reset_needed;\r\nstatic int            skyscrapers;\r\nstatic GLbbox         hot_zone;\r\nstatic int            logo_index;\r\nstatic unsigned       start_time;\r\nstatic int            scene_begin;\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic GLrgba get_light_color (float sat, float lum)\r\n{\r\n\r\n  int     index;\r\n\r\n  index = RandomVal (LIGHT_COLOR_COUNT);\r\n  return glRgbaFromHsl (light_colors[index].hue, sat, lum);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void claim (int x, int y, int width, int depth, int val)\r\n{\r\n\r\n  int     xx, yy;\r\n\r\n  for (xx = x; xx < (x + width); xx++) {\r\n    for (yy = y; yy < (y + depth); yy++) {\r\n      world[CLAMP (xx,0,WORLD_SIZE - 1)][CLAMP (yy,0,WORLD_SIZE - 1)] |= val;\r\n    }\r\n  }\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic bool claimed (int x, int y, int width, int depth)\r\n{\r\n\r\n  int     xx, yy;\r\n\r\n  for (xx = x; xx < x + width; xx++) {\r\n    for (yy = y; yy < y + depth; yy++) {\r\n      if (world[CLAMP (xx,0,WORLD_SIZE - 1)][CLAMP (yy,0,WORLD_SIZE - 1)])\r\n        return true;\r\n    }\r\n  }\r\n  return false;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void build_road (int x1, int y1, int width, int depth)\r\n{\r\n\r\n  int       lanes;\r\n  int       divider;\r\n  int       sidewalk;\r\n\r\n  //the given rectangle defines a street and its sidewalk. See which way it goes.\r\n  if (width > depth) \r\n    lanes = depth;\r\n  else\r\n    lanes = width;\r\n  //if we dont have room for both lanes and sidewalk, abort\r\n  if (lanes < 4)\r\n    return;\r\n  //if we have an odd number of lanes, give the extra to a divider.\r\n  if (lanes % 2) {\r\n    lanes--;\r\n    divider = 1;\r\n  } else\r\n    divider = 0;\r\n  //no more than 10 traffic lanes, give the rest to sidewalks\r\n  sidewalk = MAX (2, (lanes - 10));\r\n  lanes -= sidewalk;\r\n  sidewalk /= 2;\r\n  //take the remaining space and give half to each direction\r\n  lanes /= 2;\r\n  //Mark the entire rectangle as used\r\n  claim (x1, y1, width, depth, CLAIM_WALK);\r\n  //now place the directional roads\r\n  if (width > depth) {\r\n    claim (x1, y1 + sidewalk, width, lanes, CLAIM_ROAD | MAP_ROAD_WEST);\r\n    claim (x1, y1 + sidewalk + lanes + divider, width, lanes, CLAIM_ROAD | MAP_ROAD_EAST);\r\n  } else {\r\n    claim (x1 + sidewalk, y1, lanes, depth, CLAIM_ROAD | MAP_ROAD_SOUTH);\r\n    claim (x1 + sidewalk + lanes + divider, y1, lanes, depth, CLAIM_ROAD | MAP_ROAD_NORTH);\r\n  }\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic plot find_plot (int x, int z)\r\n{\r\n\r\n  plot      p;\r\n  int       x1, x2, z1, z2;\r\n\r\n  //We've been given the location of an open bit of land, but we have no \r\n  //idea how big it is. Find the boundary.\r\n  x1 = x2 = x;\r\n  while (!claimed (x1 - 1, z, 1, 1) && x1 > 0)\r\n    x1--;\r\n  while (!claimed (x2 + 1, z, 1, 1) && x2 < WORLD_SIZE)\r\n    x2++;\r\n  z1 = z2 = z;\r\n  while (!claimed (x, z1 - 1, 1, 1) && z1 > 0)\r\n    z1--;\r\n  while (!claimed (x, z2 + 1, 1, 1) && z2 < WORLD_SIZE)\r\n    z2++;\r\n  p.width = (x2 - x1);\r\n  p.depth = (z2 - z1);\r\n  p.x = x1;\r\n  p.z = z1;\r\n  return p;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic plot make_plot (int x, int z, int width, int depth)\r\n{\r\n\r\n  plot      p = {x, z, width, depth};\r\n  return p;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid do_building (plot p)\r\n{\r\n\r\n  int     height;\r\n  int     seed;\r\n  int     area;\r\n  int     type;\r\n  GLrgba  color;\r\n  bool    square;\r\n\r\n  //now we know how big the rectangle plot is. \r\n  area = p.width * p.depth;\r\n  color = WorldLightColor (RandomVal ());\r\n  seed = RandomVal ();\r\n  //Make sure the plot is big enough for a building\r\n  if (p.width < 10 || p.depth < 10)\r\n    return;\r\n  //If the area is too big for one building, sub-divide it.\r\n \r\n  if (area > 800) {\r\n    if (COIN_FLIP) {\r\n      p.width /= 2;\r\n      if (COIN_FLIP)\r\n        do_building (make_plot (p.x, p.z, p.width, p.depth));\r\n      else\r\n        do_building (make_plot (p.x + p.width, p.z, p.width, p.depth));\r\n      return;\r\n    } else {\r\n      p.depth /= 2;\r\n      if (COIN_FLIP)\r\n        do_building (make_plot (p.x, p.z, p.width, p.depth));\r\n      else\r\n        do_building (make_plot (p.x, p.z + p.depth, p.width, p.depth));\r\n      return;\r\n    }\r\n  }\r\n  if (area < 100)\r\n    return;\r\n  //The plot is \"square\" if width & depth are close\r\n  square = abs (p.width - p.depth) < 10;\r\n  //mark the land as used so other buildings don't appear here, even if we don't use it all.\r\n  claim (p.x, p.z, p.width, p.depth, CLAIM_BUILDING);\r\n  \r\n  //The roundy mod buildings look best on square plots.\r\n  if (square && p.width > 20) {\r\n    height = 45 + RandomVal (10);\r\n    modern_count++;\r\n    skyscrapers++;\r\n    new CBuilding (BUILDING_MODERN, p.x, p.z, height, p.width, p.depth, seed, color);\r\n    return;\r\n  }\r\n  /*\r\n  //Rectangular plots are a good place for Blocky style buildsing to sprawl blockily.\r\n  if (p.width > p.depth * 2 || p.depth > p.width * 2 && area > 800) {\r\n    height = 20 + RandomVal (10);\r\n    blocky_count++;\r\n    skyscrapers++;\r\n    new CBuilding (BUILDING_BLOCKY, p.x, p.z, height, p.width, p.depth, seed, color);\r\n    return;\r\n  }\r\n  */\r\n  //tower_count = -1;\r\n  //This spot isn't ideal for any particular building, but try to keep a good mix\r\n  if (tower_count < modern_count && tower_count < blocky_count) {\r\n    type = BUILDING_TOWER;\r\n    tower_count++;\r\n  } else if (blocky_count < modern_count) {\r\n    type = BUILDING_BLOCKY;\r\n    blocky_count++;\r\n  } else {\r\n    type = BUILDING_MODERN;\r\n    modern_count++;\r\n  }\r\n  height = 45 + RandomVal (10);\r\n  new CBuilding (type, p.x, p.z, height, p.width, p.depth, seed, color);\r\n  skyscrapers++;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic int build_light_strip (int x1, int z1, int direction)\r\n{\r\n\r\n  CDeco*  d;\r\n  GLrgba  color;\r\n  int     x2, z2;\r\n  int     length;\r\n  int     width, depth;\r\n  int     dir_x, dir_z;\r\n  float   size_adjust;\r\n  \r\n  //We adjust the size of the lights with this.  \r\n  size_adjust = 2.5f;\r\n  color = glRgbaFromHsl (0.09f,  0.99f,  0.85f);\r\n  switch (direction) {\r\n  case NORTH:\r\n    dir_z = 1; dir_x = 0;break;\r\n  case SOUTH:\r\n    dir_z = 1; dir_x = 0;break;\r\n  case EAST:\r\n    dir_z = 0; dir_x = 1;break;\r\n  case WEST:\r\n    dir_z = 0; dir_x = 1;break;\r\n  }\r\n  //So we know we're on the corner of an intersection\r\n  //look in the given  until we reach the end of the sidewalk\r\n  x2 = x1;\r\n  z2 = z1;\r\n  length = 0;\r\n  while (x2 > 0 && x2 < WORLD_SIZE && z2 > 0 && z2 < WORLD_SIZE) {\r\n    if ((world[x2][z2] & CLAIM_ROAD))\r\n      break;\r\n    length++;\r\n    x2 += dir_x;\r\n    z2 += dir_z;\r\n  }\r\n  if (length < 10)\r\n    return length;\r\n  width = MAX (abs(x2 - x1), 1);\r\n  depth = MAX (abs(z2 - z1), 1);\r\n  d = new CDeco;\r\n  if (direction == EAST)\r\n    d->CreateLightStrip ((float)x1, (float)z1 - size_adjust, (float)width, (float)depth + size_adjust, 2, color);\r\n  else if (direction == WEST)\r\n    d->CreateLightStrip ((float)x1, (float)z1, (float)width, (float)depth + size_adjust, 2, color);\r\n  else if (direction == NORTH)\r\n    d->CreateLightStrip ((float)x1, (float)z1, (float)width + size_adjust, (float)depth, 2, color);\r\n  else\r\n    d->CreateLightStrip ((float)x1 - size_adjust, (float)z1, (float)width + size_adjust, (float)depth, 2, color);\r\n  return length;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nstatic void do_reset (void)\r\n{\r\n  \r\n  int       x, y;\r\n  int       width, depth, height;\r\n  int       attempts;\r\n  bool      broadway_done;\r\n  bool      road_left, road_right;\r\n  GLrgba    light_color;\r\n  GLrgba    building_color;\r\n  float     west_street, north_street, east_street, south_street;\r\n\r\n  //Re-init Random to make the same city each time. Helpful when running tests.\r\n  RandomInit (6);\r\n  reset_needed = false;\r\n  broadway_done = false;\r\n  skyscrapers = 0;\r\n  logo_index = 0;\r\n  scene_begin = 0;\r\n  tower_count = blocky_count = modern_count = 0;\r\n  hot_zone = glBboxClear ();\r\n  EntityClear ();\r\n  LightClear ();\r\n  CarClear ();\r\n  TextureReset ();\r\n  //Pick a tint for the bloom \r\n  bloom_color = get_light_color(0.5f + (float)RandomVal (10) / 20.0f, 0.75f);\r\n  light_color = glRgbaFromHsl (0.11f, 1.0f, 0.65f);\r\n  ZeroMemory (world, WORLD_SIZE * WORLD_SIZE);\r\n  for (y = WORLD_EDGE; y < WORLD_SIZE - WORLD_EDGE; y += RandomVal (25) + 25) {\r\n    if (!broadway_done && y > WORLD_HALF - 20) {\r\n      build_road (0, y, WORLD_SIZE, 19);\r\n      y += 20;\r\n      broadway_done = true;\r\n    } else {\r\n      depth = 6 + RandomVal (6);\r\n      if (y < WORLD_HALF / 2)\r\n        north_street = (float)(y + depth / 2);\r\n      if (y < (WORLD_SIZE - WORLD_HALF / 2))\r\n        south_street = (float)(y + depth / 2);\r\n      build_road (0, y, WORLD_SIZE, depth);\r\n    }\r\n  }\r\n\r\n  broadway_done = false;\r\n  for (x = WORLD_EDGE; x < WORLD_SIZE - WORLD_EDGE; x += RandomVal (25) + 25) {\r\n    if (!broadway_done && x > WORLD_HALF - 20) {\r\n      build_road (x, 0, 19, WORLD_SIZE);\r\n      x += 20;\r\n      broadway_done = true;\r\n    } else {\r\n      width = 6 + RandomVal (6);\r\n      if (x <= WORLD_HALF / 2)\r\n        west_street = (float)(x + width / 2);\r\n      if (x <= WORLD_HALF + WORLD_HALF / 2)\r\n        east_street = (float)(x + width / 2);\r\n      build_road (x, 0, width, WORLD_SIZE);\r\n    }\r\n  }\r\n  //We kept track of the positions of streets that will outline the high-detail hot zone \r\n  //in the middle of the world.  Save this in a bounding box so that later we can \r\n  //have the camera fly around without clipping through buildings.\r\n  hot_zone = glBboxContainPoint (hot_zone, glVector (west_street, 0.0f, north_street)); \r\n  hot_zone = glBboxContainPoint (hot_zone, glVector (east_street, 0.0f, south_street));\r\n  \r\n  //Scan for places to put runs of streetlights on the east & west side of the road\r\n  for (x = 1; x < WORLD_SIZE - 1; x++) {\r\n    for (y = 0; y < WORLD_SIZE; y++) {\r\n      //if this isn't a bit of sidewalk, then keep looking\r\n      if (!(world[x][y] & CLAIM_WALK))\r\n        continue;\r\n      //If it's used as a road, skip it.\r\n      if ((world[x][y] & CLAIM_ROAD))\r\n        continue;\r\n      road_left = (world[x + 1][y] & CLAIM_ROAD) != 0;\r\n      road_right = (world[x - 1][y] & CLAIM_ROAD) != 0;\r\n      //if the cells to our east and west are not road, then we're not on a corner. \r\n      if (!road_left && !road_right)\r\n        continue;\r\n      //if the cell to our east AND west is road, then we're on a median. skip it\r\n      if (road_left && road_right)\r\n        continue;\r\n      y += build_light_strip (x, y, road_right ? SOUTH : NORTH);\r\n    }\r\n  }\r\n  //Scan for places to put runs of streetlights on the north & south side of the road\r\n  for (y = 1; y < WORLD_SIZE - 1; y++) {\r\n    for (x = 1; x < WORLD_SIZE - 1; x++) {\r\n      //if this isn't a bit of sidewalk, then keep looking\r\n      if (!(world[x][y] & CLAIM_WALK))\r\n        continue;\r\n      //If it's used as a road, skip it.\r\n      if ((world[x][y] & CLAIM_ROAD))\r\n        continue;\r\n      road_left = (world[x][y + 1] & CLAIM_ROAD) != 0;\r\n      road_right = (world[x][y - 1] & CLAIM_ROAD) != 0;\r\n      //if the cell to our east AND west is road, then we're on a median. skip it\r\n      if (road_left && road_right)\r\n        continue;\r\n      //if the cells to our north and south are not road, then we're not on a corner. \r\n      if (!road_left && !road_right)\r\n        continue;\r\n      x += build_light_strip (x, y, road_right ? EAST : WEST);\r\n    }\r\n  }\r\n  \r\n  \r\n  //Scan over the center area of the map and place the big buildings \r\n  attempts = 0;\r\n   while (skyscrapers < 50 && attempts < 350) {\r\n    x = (WORLD_HALF / 2) + (RandomVal () % WORLD_HALF);\r\n    y = (WORLD_HALF / 2) + (RandomVal () % WORLD_HALF);\r\n    if (!claimed (x, y, 1,1)) {\r\n      do_building (find_plot (x, y));\r\n      skyscrapers++;\r\n    }\r\n    attempts++;\r\n  }\r\n  \r\n  //now blanket the rest of the world with lesser buildings\r\n  for (x = 0; x < WORLD_SIZE; x ++) {\r\n    for (y = 0; y < WORLD_SIZE; y ++) {\r\n      if (world[CLAMP (x,0,WORLD_SIZE)][CLAMP (y,0,WORLD_SIZE)])\r\n        continue;\r\n      width = 12 + RandomVal (20);\r\n      depth = 12 + RandomVal (20);\r\n      height = MIN (width, depth);\r\n      if (x < 30 || y < 30 || x > WORLD_SIZE - 30 || y > WORLD_SIZE - 30)\r\n        height = RandomVal (15) + 20;\r\n      else if (x < WORLD_HALF / 2)\r\n        height /= 2;\r\n      while (width > 8 && depth > 8) {\r\n        if (!claimed (x, y, width, depth)) {\r\n          claim (x, y, width, depth,CLAIM_BUILDING);\r\n          building_color = WorldLightColor (RandomVal ());\r\n          //if we're out of the hot zone, use simple buildings\r\n          if (x < hot_zone.min.x || x > hot_zone.max.x || y < hot_zone.min.z || y > hot_zone.max.z) {\r\n            height = 5 + RandomVal (height) + RandomVal (height);\r\n            new CBuilding (BUILDING_SIMPLE, x + 1, y + 1, height, width - 2, depth - 2, RandomVal (), building_color);\r\n          } else { //use fancy buildings.\r\n            height = 15 + RandomVal (15);\r\n            width -=2;\r\n            depth -=2;\r\n            if (COIN_FLIP) \r\n              new CBuilding (BUILDING_TOWER, x + 1, y + 1, height, width, depth, RandomVal (), building_color);\r\n            else\r\n              new CBuilding (BUILDING_BLOCKY, x + 1, y + 1, height, width, depth, RandomVal (), building_color);\r\n          }\r\n          break;\r\n        }\r\n        width--;\r\n        depth--;\r\n      }\r\n      //leave big gaps near the edge of the map, no need to pack detail there.\r\n      if (y < WORLD_EDGE || y > WORLD_SIZE - WORLD_EDGE) \r\n        y += 32;\r\n    }\r\n    //leave big gaps near the edge of the map\r\n    if (x < WORLD_EDGE || x > WORLD_SIZE - WORLD_EDGE) \r\n      x += 28;\r\n  }\r\n  \r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  This will return a random color which is suitible for light sources, taken\r\n  from a narrow group of hues. (Yellows, oranges, blues.)\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba WorldLightColor (unsigned index)\r\n{\r\n\r\n  index %= LIGHT_COLOR_COUNT;\r\n  return glRgbaFromHsl (light_colors[index].hue, light_colors[index].sat, light_colors[index].lum);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nchar WorldCell (int x, int y)\r\n{\r\n\r\n  return world[CLAMP (x, 0,WORLD_SIZE - 1)][CLAMP (y, 0, WORLD_SIZE - 1)];\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba WorldBloomColor ()\r\n{\r\n\r\n  return bloom_color;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint WorldLogoIndex ()\r\n{\r\n\r\n  return logo_index++;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLbbox WorldHotZone ()\r\n{\r\n\r\n  return hot_zone;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WorldTerm (void)\r\n{\r\n\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WorldReset (void)\r\n{\r\n\r\n  //If we're already fading out, then this is the developer hammering on the \r\n  //\"rebuild\" button.  Let's hurry things up for the nice man...\r\n  if (fade_state == FADE_OUT) \r\n    do_reset ();\r\n  //If reset is called but the world isn't ready, then don't bother fading out.\r\n  //The program probably just started.\r\n  fade_state = FADE_OUT;\r\n  fade_start = GetTickCount ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WorldRender ()\r\n{\r\n\r\n  if (!SHOW_DEBUG_GROUND) \r\n    return;\r\n  //Render a single texture over the city that shows traffic lanes\r\n  glDepthMask (false);\r\n  glDisable (GL_CULL_FACE);\r\n  glDisable (GL_BLEND);\r\n  glEnable (GL_TEXTURE_2D);\r\n  glColor3f (1,1,1);\r\n  glBindTexture (GL_TEXTURE_2D, 0);\r\n  glBegin (GL_QUADS);\r\n  glTexCoord2f (0, 0);   glVertex3f ( 0., 0, 0);\r\n  glTexCoord2f (0, 1);   glVertex3f ( 0, 0,  1024);\r\n  glTexCoord2f (1, 1);   glVertex3f ( 1024, 0, 1024);\r\n  glTexCoord2f (1, 0);   glVertex3f ( 1024, 0, 0);\r\n  glEnd ();\r\n  glDepthMask (true);\r\n\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat WorldFade (void)\r\n{\r\n\r\n  return fade_current;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint WorldSceneBegin ()\r\n{\r\n\r\n  return scene_begin;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n  How long since this current iteration of the city went on display,\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nint WorldSceneElapsed ()\r\n{\r\n\r\n  int     elapsed;\r\n\r\n  if (!EntityReady () || !WorldSceneBegin ())\r\n    elapsed = 1;\r\n  else\r\n    elapsed = GetTickCount () - (WorldSceneBegin ());\r\n  elapsed = MAX (elapsed, 1);\r\n  return elapsed;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WorldUpdate (void)\r\n{\r\n\r\n  unsigned      fade_delta;\r\n  int           now;\r\n\r\n  now = GetTickCount ();\r\n  if (reset_needed) {\r\n    do_reset (); //Now we've faded out the scene, rebuild it\r\n  }\r\n  if (fade_state != FADE_IDLE) {\r\n    if (fade_state == FADE_WAIT && TextureReady () && EntityReady ()) {\r\n        fade_state = FADE_IN;\r\n        fade_start = now;\r\n        fade_current = 1.0f;\r\n    }    \r\n    fade_delta = now - fade_start;\r\n    //See if we're done fading in or out\r\n    if (fade_delta > FADE_TIME && fade_state != FADE_WAIT) {\r\n      if (fade_state == FADE_OUT) {\r\n        reset_needed = true;\r\n        fade_state = FADE_WAIT;\r\n        fade_current = 1.0f;\r\n      } else {\r\n        fade_state = FADE_IDLE;\r\n        fade_current = 0.0f;\r\n        start_time = time (NULL);\r\n        scene_begin = GetTickCount ();\r\n      }\r\n    } else {\r\n      fade_current = (float)fade_delta / FADE_TIME;\r\n      if (fade_state == FADE_IN)\r\n        fade_current = 1.0f - fade_current;\r\n      if (fade_state == FADE_WAIT)\r\n        fade_current = 1.0f;\r\n    }\r\n    if (!TextureReady ())\r\n      fade_current = 1.0f;\r\n  } \r\n  if (fade_state == FADE_IDLE && !TextureReady ()) {\r\n    fade_state = FADE_IN;\r\n    fade_start = now;\r\n  }\r\n  if (fade_state == FADE_IDLE && WorldSceneElapsed () > RESET_INTERVAL)\r\n    WorldReset ();\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid WorldInit (void)\r\n{\r\n\r\n  last_update = GetTickCount ();\r\n  for (int i = 0; i < CARS; i++)\r\n    new CCar ();\r\n  sky = new CSky ();\r\n  WorldReset ();\r\n  fade_state = FADE_OUT;\r\n  fade_start = 0;\r\n\r\n}\r\n"
  },
  {
    "path": "World.h",
    "content": "\r\nGLrgba    WorldBloomColor ();\r\nchar      WorldCell (int x, int y);\r\nGLrgba    WorldLightColor (unsigned index);\r\nint       WorldLogoIndex ();\r\nGLbbox    WorldHotZone ();\r\nvoid      WorldInit (void);\r\nfloat     WorldFade (void);\r\nvoid      WorldRender ();\r\nvoid      WorldReset (void);\r\nint       WorldSceneBegin ();\r\nint       WorldSceneElapsed ();\r\nvoid      WorldTerm (void);\r\nvoid      WorldUpdate (void);\r\n\r\n\r\n"
  },
  {
    "path": "glBbox.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  glBbox.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n  \r\n  This module has a few functions useful for manipulating the bounding-box \r\n  structs.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#define MAX_VALUE               999999999999999.9f\r\n\r\n#include <math.h>\r\n\r\n#include \"macro.h\"\r\n#include \"glTypes.h\"\r\n\r\n/*-----------------------------------------------------------------------------\r\nDoes the given point fall within the given Bbox?\r\n-----------------------------------------------------------------------------*/\r\n\r\nbool glBboxTestPoint (GLbbox box, GLvector point)\r\n{\r\n\r\n  if (point.x > box.max.x || point.x < box.min.x)\r\n    return false;\r\n  if (point.y > box.max.y || point.y < box.min.y)\r\n    return false;\r\n  if (point.z > box.max.z || point.z < box.min.z)\r\n    return false;\r\n  return true;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nExpand Bbox (if needed) to contain given point\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLbbox glBboxContainPoint (GLbbox box, GLvector point)\r\n{\r\n\r\n  box.min.x = MIN (box.min.x, point.x);\r\n  box.min.y = MIN (box.min.y, point.y);\r\n  box.min.z = MIN (box.min.z, point.z);\r\n  box.max.x = MAX (box.max.x, point.x);\r\n  box.max.y = MAX (box.max.y, point.y);\r\n  box.max.z = MAX (box.max.z, point.z);\r\n  return box;\r\n  \r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nThis will invalidate the bbox. \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLbbox glBboxClear (void)\r\n{\r\n\r\n  GLbbox      result;\r\n\r\n  result.max = glVector (-MAX_VALUE, -MAX_VALUE, -MAX_VALUE);\r\n  result.min = glVector ( MAX_VALUE,  MAX_VALUE,  MAX_VALUE);\r\n  return result;\r\n\r\n}\r\n\r\n\r\n"
  },
  {
    "path": "glMatrix.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  glMatrix.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n  \r\n  Functions useful for manipulating the Matrix struct\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n\r\n#define M(e,x,y)                (e.elements[x][y])\r\n\r\n/*** Order type constants, constructors, extractors ***/\r\n\r\n    /* There are 24 possible conventions, designated by:    */\r\n    /*\t  o EulAxI = axis used initially\t\t    */\r\n    /*\t  o EulPar = parity of axis permutation\t\t    */\r\n    /*\t  o EulRep = repetition of initial axis as last\t    */\r\n    /*\t  o EulFrm = frame from which axes are taken\t    */\r\n    /* Axes I,J,K will be a permutation of X,Y,Z.\t    */\r\n    /* Axis H will be either I or K, depending on EulRep.   */\r\n    /* Frame S takes axes from initial static frame.\t    */\r\n    /* If ord = (AxI=X, Par=Even, Rep=No, Frm=S), then\t    */\r\n    /* {a,b,c,ord} means Rz(c)Ry(b)Rx(a), where Rz(c)v\t    */\r\n    /* rotates v around Z by c radians.\t\t\t    */\r\n\r\n#define EulFrmS\t     0\r\n#define EulFrmR\t     1\r\n#define EulFrm(ord)  ((unsigned)(ord)&1)\r\n#define EulRepNo     0\r\n#define EulRepYes    1\r\n#define EulRep(ord)  (((unsigned)(ord)>>1)&1)\r\n#define EulParEven   0\r\n#define EulParOdd    1\r\n#define EulPar(ord)  (((unsigned)(ord)>>2)&1)\r\n#define EulSafe\t     \"\\000\\001\\002\\000\"\r\n#define EulNext\t     \"\\001\\002\\000\\001\"\r\n#define EulAxI(ord)  ((int)(EulSafe[(((unsigned)(ord)>>3)&3)]))\r\n#define EulAxJ(ord)  ((int)(EulNext[EulAxI(ord)+(EulPar(ord)==EulParOdd)]))\r\n#define EulAxK(ord)  ((int)(EulNext[EulAxI(ord)+(EulPar(ord)!=EulParOdd)]))\r\n#define EulAxH(ord)  ((EulRep(ord)==EulRepNo)?EulAxK(ord):EulAxI(ord))\r\n    /* EulGetOrd unpacks all useful information about order simultaneously. */\r\n#define EulGetOrd(ord,i,j,k,h,n,s,f) {unsigned o=ord;f=o&1;o>>=1;s=o&1;o>>=1;\\\r\n    n=o&1;o>>=1;i=EulSafe[o&3];j=EulNext[i+n];k=EulNext[i+1-n];h=s?k:i;}\r\n    /* EulOrd creates an order value between 0 and 23 from 4-tuple choices. */\r\n#define EulOrd(i,p,r,f)\t   (((((((i)<<1)+(p))<<1)+(r))<<1)+(f))\r\n    /* Static axes */\r\n#define EulOrdXYZs    EulOrd(X,EulParEven,EulRepNo,EulFrmS)\r\n#define EulOrdXYXs    EulOrd(X,EulParEven,EulRepYes,EulFrmS)\r\n#define EulOrdXZYs    EulOrd(X,EulParOdd,EulRepNo,EulFrmS)\r\n#define EulOrdXZXs    EulOrd(X,EulParOdd,EulRepYes,EulFrmS)\r\n#define EulOrdYZXs    EulOrd(Y,EulParEven,EulRepNo,EulFrmS)\r\n#define EulOrdYZYs    EulOrd(Y,EulParEven,EulRepYes,EulFrmS)\r\n#define EulOrdYXZs    EulOrd(Y,EulParOdd,EulRepNo,EulFrmS)\r\n#define EulOrdYXYs    EulOrd(Y,EulParOdd,EulRepYes,EulFrmS)\r\n#define EulOrdZXYs    EulOrd(Z,EulParEven,EulRepNo,EulFrmS)\r\n#define EulOrdZXZs    EulOrd(Z,EulParEven,EulRepYes,EulFrmS)\r\n#define EulOrdZYXs    EulOrd(Z,EulParOdd,EulRepNo,EulFrmS)\r\n#define EulOrdZYZs    EulOrd(Z,EulParOdd,EulRepYes,EulFrmS)\r\n    /* Rotating axes */\r\n#define EulOrdZYXr    EulOrd(X,EulParEven,EulRepNo,EulFrmR)\r\n#define EulOrdXYXr    EulOrd(X,EulParEven,EulRepYes,EulFrmR)\r\n#define EulOrdYZXr    EulOrd(X,EulParOdd,EulRepNo,EulFrmR)\r\n#define EulOrdXZXr    EulOrd(X,EulParOdd,EulRepYes,EulFrmR)\r\n#define EulOrdXZYr    EulOrd(Y,EulParEven,EulRepNo,EulFrmR)\r\n#define EulOrdYZYr    EulOrd(Y,EulParEven,EulRepYes,EulFrmR)\r\n#define EulOrdZXYr    EulOrd(Y,EulParOdd,EulRepNo,EulFrmR)\r\n#define EulOrdYXYr    EulOrd(Y,EulParOdd,EulRepYes,EulFrmR)\r\n#define EulOrdYXZr    EulOrd(Z,EulParEven,EulRepNo,EulFrmR)\r\n#define EulOrdZXZr    EulOrd(Z,EulParEven,EulRepYes,EulFrmR)\r\n#define EulOrdXYZr    EulOrd(Z,EulParOdd,EulRepNo,EulFrmR)\r\n#define EulOrdZYZr    EulOrd(Z,EulParOdd,EulRepYes,EulFrmR)\r\n\r\n#include <math.h>\r\n#include <float.h>\r\n\r\n#include \"macro.h\"\r\n#include \"glTypes.h\"\r\n\r\nstatic float      identity[4][4] = \r\n{\r\n  {1.0f, 0.0f, 0.0f, 0.0f},\r\n  {0.0f, 1.0f, 0.0f, 0.0f},\r\n  {0.0f, 0.0f, 1.0f, 0.0f},\r\n  {0.0f, 0.0f, 0.0f, 1.0f},\r\n};\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid* glMatrixCreate (void)\r\n{\r\n\r\n  GLmatrix*       m;\r\n  int             x;\r\n  int             y;\r\n\r\n  m = new GLmatrix;\r\n  for (x = 0; x < 4; x++) {\r\n    for (y = 0; y < 4; y++) {\r\n      m -> elements[x][y] = identity[x][y];\r\n    }\r\n  }\r\n  return (void*)m;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLmatrix glMatrixIdentity (void)\r\n{\r\n\r\n  GLmatrix        m;\r\n  int             x;\r\n  int             y;\r\n\r\n  for (x = 0; x < 4; x++) {\r\n    for (y = 0; y < 4; y++) {\r\n      M(m, x, y) = identity[x][y];\r\n    }\r\n  }\r\n  return m;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nvoid glMatrixElementsSet (GLmatrix* m, float* in)\r\n{\r\n\r\n  m -> elements[0][0] = in[0];\r\n  m -> elements[0][1] = in[1];\r\n  m -> elements[0][2] = in[2];\r\n  m -> elements[0][3] = in[3];\r\n\r\n  m -> elements[1][0] = in[4];\r\n  m -> elements[1][1] = in[5];\r\n  m -> elements[1][2] = in[6];\r\n  m -> elements[1][3] = in[7];\r\n\r\n  m -> elements[2][0] = in[8];\r\n  m -> elements[2][1] = in[9];\r\n  m -> elements[2][2] = in[10];\r\n  m -> elements[2][3] = in[11];\r\n  \r\n  m -> elements[3][0] = in[12];\r\n  m -> elements[3][1] = in[13];\r\n  m -> elements[3][2] = in[14];\r\n  m -> elements[3][3] = in[15];\r\n\r\n}\r\n\r\n/*---------------------------------------------------------------------------\r\nA matrix multiplication (dot product) of two 4x4 matrices.\r\n---------------------------------------------------------------------------*/\r\n\r\nGLmatrix glMatrixMultiply (GLmatrix a, GLmatrix b)\r\n{\r\n\r\n  GLmatrix        result;\r\n  \r\n  M(result, 0,0) = M(a, 0,0) * M(b, 0, 0) + M(a, 1,0) * M(b, 0, 1) + M(a, 2,0) * M(b, 0, 2);\r\n  M(result, 1,0) = M(a, 0,0) * M(b, 1, 0) + M(a, 1,0) * M(b, 1, 1) + M(a, 2,0) * M(b, 1, 2);\r\n  M(result, 2,0) = M(a, 0,0) * M(b, 2, 0) + M(a, 1,0) * M(b, 2, 1) + M(a, 2,0) * M(b, 2, 2);\r\n  M(result, 3,0) = M(a, 0,0) * M(b, 3, 0) + M(a, 1,0) * M(b, 3, 1) + M(a, 2,0) * M(b, 3, 2) + M(a, 3,0);\r\n  \r\n  M(result, 0,1) = M(a, 0,1) * M(b, 0, 0) + M(a, 1,1) * M(b, 0, 1) + M(a, 2,1) * M(b, 0, 2);\r\n  M(result, 1,1) = M(a, 0,1) * M(b, 1, 0) + M(a, 1,1) * M(b, 1, 1) + M(a, 2,1) * M(b, 1, 2);\r\n  M(result, 2,1) = M(a, 0,1) * M(b, 2, 0) + M(a, 1,1) * M(b, 2, 1) + M(a, 2,1) * M(b, 2, 2);\r\n  M(result, 3,1) = M(a, 0,1) * M(b, 3, 0) + M(a, 1,1) * M(b, 3, 1) + M(a, 2,1) * M(b, 3, 2) + M(a, 3,1);\r\n\r\n  M(result, 0,2) = M(a, 0,2) * M(b, 0, 0) + M(a, 1,2) * M(b, 0, 1) + M(a, 2,2) * M(b, 0, 2);\r\n  M(result, 1,2) = M(a, 0,2) * M(b, 1, 0) + M(a, 1,2) * M(b, 1, 1) + M(a, 2,2) * M(b, 1, 2);\r\n  M(result, 2,2) = M(a, 0,2) * M(b, 2, 0) + M(a, 1,2) * M(b, 2, 1) + M(a, 2,2) * M(b, 2, 2);\r\n  M(result, 3,2) = M(a, 0,2) * M(b, 3, 0) + M(a, 1,2) * M(b, 3, 1) + M(a, 2,2) * M(b, 3, 2) + M(a, 3,2);\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector glMatrixTransformPoint (GLmatrix m, GLvector in)\r\n{\r\n\r\n  GLvector              out;\r\n\r\n  out.x = M(m,0,0) * in.x + M(m,1,0) * in.y + M(m,2,0) * in.z + M(m,3,0);\r\n  out.y = M(m,0,1) * in.x + M(m,1,1) * in.y + M(m,2,1) * in.z + M(m,3,1);\r\n  out.z = M(m,0,2) * in.x + M(m,1,2) * in.y + M(m,2,2) * in.z + M(m,3,2);\r\n  return out;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLmatrix glMatrixTranslate (GLmatrix m, GLvector in)\r\n{\r\n\r\n  GLvector  old;\r\n\r\n  old.x = M(m,3,0);\r\n  old.y = M(m,3,1);\r\n  old.z = M(m,3,2);\r\n  M(m, 3, 0) = 0.0f;\r\n  M(m, 3, 1) = 0.0f;\r\n  M(m, 3, 2) = 0.0f;\r\n  in = glMatrixTransformPoint (m, in);\r\n  M(m, 3, 0) = old.x;\r\n  M(m, 3, 1) = old.y;\r\n  M(m, 3, 2) = old.z;\r\n  M(m,3,0) += in.x;\r\n  M(m,3,1) += in.y;\r\n  M(m,3,2) += in.z;\r\n  return m;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLmatrix glMatrixRotate (GLmatrix m, float theta, float x, float y, float z)\r\n{\r\n\r\n  GLmatrix              r;\r\n  float                 length;\r\n  float                 s, c, t;\r\n  GLvector              in;\r\n\r\n  theta *= DEGREES_TO_RADIANS;\r\n  r = glMatrixIdentity ();\r\n  length = (float)sqrt (x * x + y * y + z * z); \r\n  if (length < 0.00001f)\r\n    return m;\r\n  x /= length;\r\n  y /= length;\r\n  z /= length;\r\n  s = (float)sin (theta);\r\n  c = (float)cos (theta);\r\n  t = 1.0f - c;  \r\n \r\n  in.x = in.y = in.z = 1.0f;\r\n  M(r, 0,0) = t*x*x + c;\r\n  M(r, 1,0) = t*x*y - s*z;\r\n  M(r, 2,0) = t*x*z + s*y;\r\n  M(r, 3,0) = 0;\r\n\r\n  M(r, 0,1) = t*x*y + s*z;\r\n  M(r, 1,1) = t*y*y + c;\r\n  M(r, 2,1) = t*y*z - s*x;\r\n  M(r, 3,1) = 0;\r\n\r\n  M(r, 0,2) = t*x*z - s*y;\r\n  M(r, 1,2) = t*y*z + s*x;\r\n  M(r, 2,2) = t*z*z + c;\r\n  M(r, 3,2) = 0;\r\n\r\n  m = glMatrixMultiply (m, r);\r\n  return m;\r\n\r\n}\r\n\r\n/* Convert matrix to Euler angles (in radians). */\r\nGLvector glMatrixToEuler (GLmatrix mat, int order)\r\n{\r\n  GLvector    ea;\r\n  int         i,j,k,h,n,s,f;\r\n\r\n  EulGetOrd (order,i,j,k,h,n,s,f);\r\n  if (s==EulRepYes) {\r\n\t  float sy = (float)sqrt(mat.elements[i][j]*mat.elements[i][j] + mat.elements[i][k]*mat.elements[i][k]);\r\n\t  if (sy > 16 * FLT_EPSILON) {\r\n\t      ea.x = (float)atan2(mat.elements[i][j], mat.elements[i][k]);\r\n\t      ea.y = (float)atan2(sy, mat.elements[i][i]);\r\n\t      ea.z = (float)atan2(mat.elements[j][i], -mat.elements[k][i]);\r\n\t  } else {\r\n\t      ea.x = (float)atan2(-mat.elements[j][k], mat.elements[j][j]);\r\n\t      ea.y = (float)atan2(sy, mat.elements[i][i]);\r\n\t      ea.z = 0;\r\n\t  }\r\n  } else {\r\n\t  float cy = (float)sqrt(mat.elements[i][i]*mat.elements[i][i] + mat.elements[j][i]*mat.elements[j][i]);\r\n\t  if (cy > 16*FLT_EPSILON) {\r\n\t      ea.x = (float)atan2(mat.elements[k][j], mat.elements[k][k]);\r\n\t      ea.y = (float)atan2(-mat.elements[k][i], cy);\r\n\t      ea.z = (float)atan2(mat.elements[j][i], mat.elements[i][i]);\r\n\t  } else {\r\n\t      ea.x = (float)atan2(-mat.elements[j][k], mat.elements[j][j]);\r\n\t      ea.y = (float)atan2(-mat.elements[k][i], cy);\r\n\t      ea.z = 0;\r\n\t  }\r\n  }\r\n  if (n==EulParOdd) {\r\n    ea.x = -ea.x;  \r\n    ea.y = - ea.y; \r\n    ea.z = -ea.z;\r\n  }\r\n  if (f==EulFrmR) {\r\n    float t = ea.x; \r\n    ea.x = ea.z; \r\n    ea.z = t;\r\n  }\r\n  //ea.w = order;\r\n  return (ea);\r\n}\r\n"
  },
  {
    "path": "glQuat.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  glQuat.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  Functions for dealing with Quaternions\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <windows.h>\r\n#include <float.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n\r\n#include \"math.h\"\r\n#include \"glTypes.h\"\r\n\r\nenum QuatPart {X, Y, Z, W};\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLquat glQuat (float x, float y, float z, float w)\r\n{\r\n\r\n  GLquat result;\r\n\r\n  result.x = x;\r\n  result.y = y;\r\n  result.z = z;\r\n  result.w = w;\r\n  return result;\r\n\r\n}\r\n\r\n\r\n/* Convert quaternion to Euler angles (in radians). */\r\n/*\r\nEulerAngles Eul_FromQuat(Quat q, int order)\r\n{\r\n    HMatrix M;\r\n    double Nq = q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w;\r\n    double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0;\r\n    double xs = q.x*s,\t  ys = q.y*s,\t zs = q.z*s;\r\n    double wx = q.w*xs,\t  wy = q.w*ys,\t wz = q.w*zs;\r\n    double xx = q.x*xs,\t  xy = q.x*ys,\t xz = q.x*zs;\r\n    double yy = q.y*ys,\t  yz = q.y*zs,\t zz = q.z*zs;\r\n    M[X][X] = 1.0 - (yy + zz); M[X][Y] = xy - wz; M[X][Z] = xz + wy;\r\n    M[Y][X] = xy + wz; M[Y][Y] = 1.0 - (xx + zz); M[Y][Z] = yz - wx;\r\n    M[Z][X] = xz - wy; M[Z][Y] = yz + wx; M[Z][Z] = 1.0 - (xx + yy);\r\n    M[W][X]=M[W][Y]=M[W][Z]=M[X][W]=M[Y][W]=M[Z][W]=0.0; M[W][W]=1.0;\r\n    return (Eul_FromHMatrix(M, order));\r\n}\r\n*/\r\n\r\nGLvector glQuatToEuler (GLquat q, int order)\r\n{\r\n    GLmatrix M;\r\n\r\n    float Nq = q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w;\r\n    float s = (Nq > 0.0f) ? (2.0f / Nq) : 0.0f;\r\n    float xs = q.x*s,\t  ys = q.y*s,\t zs = q.z*s;\r\n    float wx = q.w*xs,\t  wy = q.w*ys,\t wz = q.w*zs;\r\n    float xx = q.x*xs,\t  xy = q.x*ys,\t xz = q.x*zs;\r\n    float yy = q.y*ys,\t  yz = q.y*zs,\t zz = q.z*zs;\r\n    M.elements[X][X] = 1.0f - (yy + zz); M.elements[X][Y] = xy - wz;         M.elements[X][Z] = xz + wy;\r\n    M.elements[Y][X] = xy + wz;         M.elements[Y][Y] = 1.0f - (xx + zz); M.elements[Y][Z] = yz - wx;\r\n    M.elements[Z][X] = xz - wy;         M.elements[Z][Y] = yz + wx;         M.elements[Z][Z] = 1.0f - (xx + yy);\r\n    M.elements[W][X] = M.elements[W][Y] = \r\n      M.elements[W][Z] = M.elements[X][W] = \r\n      M.elements[Y][W] = M.elements[Z][W] = 0.0f; \r\n    M.elements[W][W] = 1.0f;\r\n    return (glMatrixToEuler(M, order));\r\n}\r\n"
  },
  {
    "path": "glRgba.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  glRgba.cpp\r\n\r\n  2009 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  Functions for dealing with RGBA color values.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <windows.h>\r\n#include <stdio.h>\r\n#include <gl\\gl.h>\r\n#include <math.h>\r\n\r\n#include \"math.h\"\r\n#include \"glTypes.h\"\r\n#include \"macro.h\"\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaFromHsl (float h, float sl, float l)\r\n{\r\n  \r\n  float v;\r\n  float r,g,b;\r\n  \r\n  \r\n  r = l;   // default to gray\r\n  g = l;\r\n  b = l;\r\n  v = (l <= 0.5f) ? (l * (1.0f + sl)) : (l + sl - l * sl);\r\n  if (v > 0)  {\r\n    float m;\r\n    float sv;\r\n    int sextant;\r\n    float fract, vsf, mid1, mid2;\r\n   \r\n    m = l + l - v;\r\n    sv = (v - m ) / v;\r\n    h *= 6.0f;\r\n    sextant = (int)h;\r\n    fract = h - sextant;\r\n    vsf = v * sv * fract;\r\n    mid1 = m + vsf;\r\n    mid2 = v - vsf;\r\n    switch (sextant) {\r\n    case 0:\r\n      r = v;  g = mid1; b = m;\r\n      break;\r\n    case 1:\r\n      r = mid2; g = v;  b = m;\r\n      break;\r\n    case 2:\r\n      r = m;  g = v;  b = mid1;\r\n      break;\r\n    case 3:\r\n      r = m; g = mid2; b = v;\r\n      break;\r\n    case 4:\r\n      r = mid1; g = m; b = v;\r\n      break;\r\n    case 5:\r\n      r = v;  g = m; b = mid2;\r\n      break;\r\n    }\r\n  }\r\n  return glRgba (r, g, b);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaInterpolate (GLrgba c1, GLrgba c2, float delta)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = MathInterpolate (c1.red, c2.red, delta);\r\n  result.green = MathInterpolate (c1.green, c2.green, delta);\r\n  result.blue = MathInterpolate (c1.blue, c2.blue, delta);\r\n  result.alpha = MathInterpolate (c1.alpha, c2.alpha, delta);\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaAdd (GLrgba c1, GLrgba c2)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = c1.red + c2.red;\r\n  result.green = c1.green + c2.green;\r\n  result.blue = c1.blue + c2.blue;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaSubtract (GLrgba c1, GLrgba c2)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = c1.red - c2.red;\r\n  result.green = c1.green - c2.green;\r\n  result.blue = c1.blue - c2.blue;\r\n  return result;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaMultiply (GLrgba c1, GLrgba c2)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = c1.red * c2.red;\r\n  result.green = c1.green * c2.green;\r\n  result.blue = c1.blue * c2.blue;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaScale (GLrgba c, float scale)\r\n{\r\n\r\n  c.red *= scale;\r\n  c.green *= scale;\r\n  c.blue *= scale;\r\n  return c;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgba (char* string)\r\n{\r\n\r\n  long    color;\r\n  char    buffer[10];\r\n  char*   pound;\r\n  GLrgba  result;\r\n\r\n  strncmp (buffer, string, 10);\r\n  if (pound = strchr (buffer, '#'))\r\n    pound[0] = ' ';\r\n  if (sscanf (string, \"%x\", &color) != 1)\r\n\t  return glRgba (0.0f);\r\n  result.red = (float)GetBValue (color) / 255.0f;\r\n  result.green = (float)GetGValue (color) / 255.0f;\r\n  result.blue = (float)GetRValue (color) / 255.0f;\r\n  result.alpha = 1.0f;\r\n  return result;  \r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgba (int red, int green, int blue)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = (float)red / 255.0f;\r\n  result.green = (float)green / 255.0f;\r\n  result.blue = (float)blue / 255.0f;\r\n  result.alpha = 1.0f;\r\n  return result;  \r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgba (float red, float green, float blue)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = red;\r\n  result.green = green;\r\n  result.blue = blue;\r\n  result.alpha = 1.0f;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgba (float red, float green, float blue, float alpha)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = red;\r\n  result.green = green;\r\n  result.blue = blue;\r\n  result.alpha = alpha;\r\n  return result;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgba (long c)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = (float)GetRValue (c) / 255.0f;\r\n  result.green = (float)GetGValue (c) / 255.0f;\r\n  result.blue = (float)GetBValue (c) / 255.0f;\r\n  result.alpha = 1.0f;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgba (float luminance)\r\n{\r\n\r\n  GLrgba     result;\r\n\r\n  result.red = luminance;\r\n  result.green = luminance;\r\n  result.blue = luminance;\r\n  result.alpha = 1.0f;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\nTakes the given index and returns a \"random\" color unique for that index.\r\n512 Unique values: #0 and #512 will be the same, as will #1 and #513, etc\r\nUseful for visual debugging in some situations.\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba glRgbaUnique (int i)\r\n{\r\n\r\n  GLrgba    c;\r\n\r\n  c.alpha = 1.0f;\r\n  c.red   = 0.4f + ((i & 1) ? 0.2f : 0.0f) + ((i &  8) ? 0.3f : 0.0f) - ((i &  64) ? 0.3f : 0.0f);\r\n  c.green = 0.4f + ((i & 2) ? 0.2f : 0.0f) + ((i & 32) ? 0.3f : 0.0f) - ((i & 128) ? 0.3f : 0.0f);\r\n  c.blue  = 0.4f + ((i & 4) ? 0.2f : 0.0f) + ((i & 16) ? 0.3f : 0.0f) - ((i & 256) ? 0.3f : 0.0f);\r\n  return c;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n  + operator                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba GLrgba::operator+ (const GLrgba& c)\r\n{\r\n  return glRgba (red + c.red, green + c.green, blue + c.blue, alpha);\r\n}\r\n\r\nGLrgba GLrgba::operator+ (const float& c)\r\n{\r\n  return glRgba (red + c, green + c, blue + c, alpha);\r\n} \r\n\r\nvoid GLrgba::operator+= (const GLrgba& c)\r\n{\r\n  red += c.red;\r\n  green += c.green;\r\n  blue += c.blue;\r\n}\r\n\r\nvoid GLrgba::operator+= (const float& c)\r\n{\r\n  red += c;\r\n  green += c;\r\n  blue += c;\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n  - operator                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba GLrgba::operator- (const GLrgba& c)\r\n{\r\n  return glRgba (red - c.red, green - c.green, blue - c.blue);\r\n}\r\n\r\nGLrgba GLrgba::operator- (const float& c)\r\n{\r\n  return glRgba (red - c, green - c, blue - c, alpha);\r\n}\r\n\r\nvoid GLrgba::operator-= (const GLrgba& c)\r\n{\r\n  red -= c.red;\r\n  green -= c.green;\r\n  blue -= c.blue;\r\n}\r\n\r\nvoid GLrgba::operator-= (const float& c)\r\n{\r\n  red -= c;\r\n  green -= c;\r\n  blue -= c;\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n  * operator                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba GLrgba::operator* (const GLrgba& c)\r\n{\r\n  return glRgba (red * c.red, green * c.green, blue * c.blue);\r\n}\r\n\r\nGLrgba GLrgba::operator* (const float& c)\r\n{\r\n  return glRgba (red * c, green * c, blue * c, alpha);\r\n}\r\n\r\nvoid GLrgba::operator*= (const GLrgba& c)\r\n{\r\n  red *= c.red;\r\n  green *= c.green;\r\n  blue *= c.blue;\r\n}\r\n\r\nvoid GLrgba::operator*= (const float& c)\r\n{\r\n  red *= c;\r\n  green *= c;\r\n  blue *= c;\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n  / operator                          \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLrgba GLrgba::operator/ (const GLrgba& c)\r\n{\r\n  return glRgba (red / c.red, green / c.green, blue / c.blue);\r\n}\r\n\r\nGLrgba GLrgba::operator/ (const float& c)\r\n{\r\n  return glRgba (red / c, green / c, blue / c, alpha);\r\n}\r\n\r\nvoid GLrgba::operator/= (const GLrgba& c)\r\n{\r\n  red /= c.red;\r\n  green /= c.green;\r\n  blue /= c.blue;\r\n}\r\n\r\nvoid GLrgba::operator/= (const float& c)\r\n{\r\n  red /= c;\r\n  green /= c;\r\n  blue /= c;\r\n}\r\n\r\nbool GLrgba::operator==  (const GLrgba& c)\r\n{\r\n  return (red == c.red && green == c.green && blue == c.blue);\r\n}"
  },
  {
    "path": "glTypes.h",
    "content": "#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+  (const type& c); \\\r\n  type    operator+  (const float& c);\\\r\n  void    operator+= (const type& c);\\\r\n  void    operator+= (const float& c);\\\r\n  type    operator-  (const type& c);\\\r\n  type    operator-  (const float& c);\\\r\n  void    operator-= (const type& c);\\\r\n  void    operator-= (const float& c);\\\r\n  type    operator*  (const type& c);\\\r\n  type    operator*  (const float& c);\\\r\n  void    operator*= (const type& c);\\\r\n  void    operator*= (const float& c);\\\r\n  type    operator/  (const type& c);\\\r\n  type    operator/  (const float& c);\\\r\n  void    operator/= (const type& c);\\\r\n  void    operator/= (const float& c);\\\r\n  bool    operator== (const type& c);\r\n\r\n\r\n#define JOINT_MAX_CHILDREN  8\r\n\r\nstruct GLquat\r\n{\r\n  float       x;\r\n  float       y;\r\n  float       z;\r\n  float       w;\r\n};\r\n\r\nstruct GLvector\r\n{\r\n  float       x;\r\n  float       y;\r\n  float       z;\r\n  OPERATORS(GLvector);\r\n};\r\n\r\ntypedef GLvector       GLvector3;\r\n\r\nstruct GLvector2\r\n{\r\n  float       x;\r\n  float       y;\r\n  OPERATORS(GLvector2);\r\n};\r\n\r\nstruct GLrgba\r\n{\r\n  float       red;\r\n  float       green;\r\n  float       blue;\r\n  float       alpha;\r\n  OPERATORS(GLrgba);\r\n};\r\n\r\nstruct GLmatrix\r\n{\r\n  float       elements[4][4];\r\n};\r\n\r\nstruct GLbbox\r\n{\r\n  GLvector3   min;\r\n  GLvector3   max;\r\n};\r\n\r\nstruct GLvertex\r\n{\r\n  GLvector3   position;\r\n  GLvector2   uv;\r\n  GLrgba      color;\r\n  int         bone;\r\n};\r\n\r\nstruct GLrect\r\n{\r\n  float       left;\r\n  float       top;\r\n  float       right;\r\n  float       bottom;\r\n};\r\n\r\nstruct GLtriangle\r\n{\r\n  int         v1;\r\n  int         v2;\r\n  int         v3;\r\n  int         normal1;\r\n  int         normal2;\r\n  int         normal3;\r\n};\r\n\r\n/*\r\nclass GLmodel\r\n{\r\npublic:\r\n  unsigned    vertex_count;\r\n  unsigned    triangle_count;\r\n  unsigned    normal_count;\r\n  GLvertex*   vertex;  \r\n  GLvector*   normal;\r\n  GLtriangle* triangle;\r\n\r\n  void        TriangleRender (unsigned n);\r\n  GLtriangle* TriangleAdd (unsigned v1, int unsigned, int unsigned);\r\n  GLtriangle* TriangleAdd (GLtriangle c);\r\n  void        NormalAdd (GLvector n);\r\n  void        VertexAdd (GLvertex v);\r\n              GLmodel ();\r\n              ~GLmodel ();\r\n  void        Render ();\r\n  GLbbox      BBox ();\r\nprivate:\r\n  GLbbox      m_bbox;\r\n\r\n};\r\n\r\nstruct GLkeyframe\r\n{\r\n  float     time;\r\n  GLvector  offset;\r\n  GLvector  rotation;\r\n};\r\n\r\nstruct GLsegment\r\n{\r\n  int           index;\r\n  GLvector      rotation;\r\n  GLvector      offset;\r\n  GLkeyframe    keyframes[255];\r\n  int           frame_count;\r\n};\r\n\r\nclass GLanimate\r\n{\r\npublic:\r\n                GLanimate ();\r\n  void          KeyframeAdd (int joint, float time, GLquat q);\r\n  void          TimeSet (float time);\r\n  void          PositionSet (float pos);\r\n  GLvector      Rotation (int);\r\n  GLvector      Offset (int);\r\n\r\nprivate:\r\n  GLsegment*    m_segments;\r\n  int           m_segment_count;\r\n  float         m_length;\r\n};\r\n*/\r\n\r\nGLbbox    glBboxClear (void);\r\nGLbbox    glBboxContainPoint (GLbbox box, GLvector point);\r\nbool      glBboxTestPoint (GLbbox box, GLvector point);\r\n\r\nGLrgba    glRgba (char* string);\r\nGLrgba    glRgba (float red, float green, float blue);\r\nGLrgba    glRgba (float luminance);\r\nGLrgba    glRgba (float red, float green, float blue, float alpha);\r\nGLrgba    glRgba (long c);\r\nGLrgba    glRgba (int red, int green, int blue);\r\nGLrgba    glRgbaAdd (GLrgba c1, GLrgba c2);\r\nGLrgba    glRgbaSubtract (GLrgba c1, GLrgba c2);\r\nGLrgba    glRgbaInterpolate (GLrgba c1, GLrgba c2, float delta);\r\nGLrgba    glRgbaScale (GLrgba c, float scale);\r\nGLrgba    glRgbaMultiply (GLrgba c1, GLrgba c2);\r\nGLrgba    glRgbaUnique (int i);\r\nGLrgba    glRgbaFromHsl (float h, float s, float l);\r\n\r\nGLmatrix  glMatrixIdentity (void);\r\nvoid      glMatrixElementsSet (GLmatrix* m, float* in);\r\nGLmatrix  glMatrixMultiply (GLmatrix a, GLmatrix b);\r\nGLvector  glMatrixTransformPoint (GLmatrix m, GLvector in);\r\nGLmatrix  glMatrixTranslate (GLmatrix m, GLvector in);\r\nGLmatrix  glMatrixRotate (GLmatrix m, float theta, float x, float y, float z);\r\nGLvector  glMatrixToEuler (GLmatrix mat, int order);\r\n\r\nGLquat    glQuat (float x, float y, float z, float w);\r\nGLvector  glQuatToEuler (GLquat q, int order);\r\n\r\nGLvector  glVector (float x, float y, float z);\r\nGLvector  glVectorCrossProduct (GLvector v1, GLvector v2);\r\nfloat     glVectorDotProduct (GLvector v1, GLvector v2);\r\nvoid      glVectorGl (GLvector v);\r\nGLvector  glVectorInterpolate (GLvector v1, GLvector v2, float scalar);\r\nfloat     glVectorLength (GLvector v);\r\nGLvector  glVectorNormalize (GLvector v);\r\nGLvector  glVectorReflect (GLvector3 ray, GLvector3 normal);\r\n\r\nGLvector2 glVector (float x, float y);\r\nGLvector2 glVectorAdd (GLvector2 val1, GLvector2 val2);\r\nGLvector2 glVectorSubtract (GLvector2 val1, GLvector2 val2);\r\nGLvector2 glVectorNormalize (GLvector2 v);\r\nGLvector2 glVectorInterpolate (GLvector2 v1, GLvector2 v2, float scalar);\r\nGLvector2 glVectorSinCos (float angle);\r\nfloat     glVectorLength (GLvector2 v);\r\n\r\n\r\n#endif\r\n\r\n#ifndef NULL\r\n#define NULL  0\r\n#endif\r\n\r\n"
  },
  {
    "path": "glVector2.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  Vector2.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  Functions for dealing with 2d (usually texture mapping) values.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <windows.h>\r\n#include <float.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n\r\n#include \"glTypes.h\"\r\n#include \"math.h\"\r\n#include \"macro.h\"\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 glVectorNormalize (GLvector2 v)\r\n{\r\n\r\n  float length;\r\n\r\n  length = glVectorLength (v);\r\n  if (length < 0.000001f)\r\n    return v;\r\n  return v * (1.0f / length);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat glVectorLength (GLvector2 v)\r\n{\r\n\r\n  return (float)sqrt (v.x * v.x + v.y * v.y);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 glVectorSinCos (float a)\r\n{\r\n\r\n  GLvector2      val;\r\n\r\n  a *= DEGREES_TO_RADIANS;\r\n  val.x = sinf (a);\r\n  val.y = cosf (a);\r\n  return val;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 glVector (float x, float y)\r\n{\r\n\r\n  GLvector2      val;\r\n\r\n  val.x = x;\r\n  val.y = y;\r\n  return val;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 glVectorAdd (GLvector2 val1, GLvector2 val2)\r\n{\r\n\r\n  GLvector2      result;\r\n\r\n  result.x = val1.x + val2.x;\r\n  result.y = val1.y + val2.y;\r\n  return result;\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 glVectorInterpolate (GLvector2 v1, GLvector2 v2, float scalar)\r\n{\r\n\r\n  GLvector2 result;\r\n\r\n  result.x = MathInterpolate (v1.x, v2.x, scalar);\r\n  result.y = MathInterpolate (v1.y, v2.y, scalar);\r\n  return result;\r\n\r\n}  \r\n\r\n/*-----------------------------------------------------------------------------\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 glVectorSubtract (GLvector2 val1, GLvector2 val2)\r\n{\r\n\r\n  GLvector2      result;\r\n\r\n  result.x = val1.x - val2.x;\r\n  result.y = val1.y - val2.y;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n+                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector2 GLvector2::operator+ (const GLvector2& c)\r\n{\r\n  return glVector (x + c.x, y + c.y);\r\n}\r\n\r\nGLvector2 GLvector2::operator+ (const float& c)\r\n{\r\n  return glVector (x + c, y + c);\r\n}\r\n\r\nvoid GLvector2::operator+= (const GLvector2& c)\r\n{\r\n  x += c.x;\r\n  y += c.y;\r\n}\r\n\r\nvoid GLvector2::operator+= (const float& c)\r\n{\r\n  x += c;\r\n  y += c;\r\n}\r\n\r\nGLvector2 GLvector2::operator- (const GLvector2& c)\r\n{\r\n  return glVector (x - c.x, y - c.y);\r\n}\r\n\r\nGLvector2 GLvector2::operator- (const float& c)\r\n{\r\n  return glVector (x - c, y - c);\r\n}\r\n\r\nvoid GLvector2::operator-= (const GLvector2& c)\r\n{\r\n  x -= c.x;\r\n  y -= c.y;\r\n}\r\n\r\nvoid GLvector2::operator-= (const float& c)\r\n{\r\n  x -= c;\r\n  y -= c;\r\n}\r\n\r\nGLvector2 GLvector2::operator* (const GLvector2& c)\r\n{\r\n  return glVector (x * c.x, y * c.y);\r\n}\r\n\r\nGLvector2 GLvector2::operator* (const float& c)\r\n{\r\n  return glVector (x * c, y * c);\r\n}\r\n\r\nvoid GLvector2::operator*= (const GLvector2& c)\r\n{\r\n  x *= c.x;\r\n  y *= c.y;\r\n}\r\n\r\nvoid GLvector2::operator*= (const float& c)\r\n{\r\n  x *= c;\r\n  y *= c;\r\n}\r\n\r\nGLvector2 GLvector2::operator/ (const GLvector2& c)\r\n{\r\n  return glVector (x / c.x, y / c.y);\r\n}\r\n\r\nGLvector2 GLvector2::operator/ (const float& c)\r\n{\r\n  return glVector (x / c, y / c);\r\n}\r\n\r\nvoid GLvector2::operator/= (const GLvector2& c)\r\n{\r\n  x /= c.x;\r\n  y /= c.y;\r\n}\r\n\r\nvoid GLvector2::operator/= (const float& c)\r\n{\r\n  x /= c;\r\n  y /= c;\r\n}\r\n\r\nbool GLvector2::operator== (const GLvector2& c)\r\n{\r\n  if (x == c.x && y == c.y)\r\n    return true;\r\n  return false;\r\n}"
  },
  {
    "path": "glVector3.cpp",
    "content": "/*-----------------------------------------------------------------------------\r\n\r\n  glVector3.cpp\r\n\r\n  2006 Shamus Young\r\n\r\n-------------------------------------------------------------------------------\r\n\r\n  Functions for dealing with 3d vectors.\r\n\r\n-----------------------------------------------------------------------------*/\r\n\r\n#include <windows.h>\r\n#include <float.h>\r\n#include <math.h>\r\n#include <gl\\gl.h>\r\n\r\n#include \"macro.h\"\r\n#include \"math.h\"\r\n#include \"glTypes.h\"\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector glVectorReflect (GLvector3 ray, GLvector3 normal)\r\n{\r\n\r\n  float       dot;\r\n\r\n  dot = glVectorDotProduct (ray, normal);\r\n  return ray - (normal * (2.0f * dot));\r\n\r\n}\r\n\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector3 glVector (float x, float y, float z)\r\n{\r\n\r\n  GLvector3 result;\r\n\r\n  result.x = x;\r\n  result.y = y;\r\n  result.z = z;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector3 glVectorInterpolate (GLvector3 v1, GLvector3 v2, float scalar)\r\n{\r\n\r\n  GLvector3 result;\r\n\r\n  result.x = MathInterpolate (v1.x, v2.x, scalar);\r\n  result.y = MathInterpolate (v1.y, v2.y, scalar);\r\n  result.z = MathInterpolate (v1.z, v2.z, scalar);\r\n  return result;\r\n\r\n}  \r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat glVectorLength (GLvector3 v)\r\n{\r\n\r\n  return (float)sqrt (v.x * v.x + v.y * v.y + v.z * v.z);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nfloat glVectorDotProduct (GLvector3 v1, GLvector3 v2)\r\n{\r\n\r\n  return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector3 glVectorCrossProduct (GLvector3 v1, GLvector3 v2)\r\n{\r\n\r\n  GLvector3 result;\r\n  \r\n  result.x = v1.y * v2.z - v2.y * v1.z;\r\n  result.y = v1.z * v2.x - v2.z * v1.x;\r\n  result.z = v1.x * v2.y - v2.x * v1.y;\r\n  return result;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector3 glVectorInvert (GLvector3 v)\r\n{\r\n\r\n  v.x *= -v.x;\r\n  v.y *= -v.y;\r\n  v.z *= -v.z;\r\n  return v;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector3 glVectorScale (GLvector3 v, float scale)\r\n{\r\n\r\n  v.x *= scale;\r\n  v.y *= scale;\r\n  v.z *= scale;\r\n  return v;\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector3 glVectorNormalize (GLvector3 v)\r\n{\r\n\r\n  float length;\r\n\r\n  length = glVectorLength (v);\r\n  if (length < 0.000001f)\r\n    return v;\r\n  return glVectorScale (v, 1.0f / length);\r\n\r\n}\r\n\r\n/*-----------------------------------------------------------------------------\r\n+                           \r\n-----------------------------------------------------------------------------*/\r\n\r\nGLvector GLvector::operator+ (const GLvector& c)\r\n{\r\n  return glVector (x + c.x, y + c.y, z + c.z);\r\n}\r\n\r\nGLvector GLvector::operator+ (const float& c)\r\n{\r\n  return glVector (x + c, y + c, z + c);\r\n}\r\n\r\nvoid GLvector::operator+= (const GLvector& c)\r\n{\r\n  x += c.x;\r\n  y += c.y;\r\n  z += c.z;\r\n}\r\n\r\nvoid GLvector::operator+= (const float& c)\r\n{\r\n  x += c;\r\n  y += c;\r\n  z += c;\r\n}\r\n\r\nGLvector GLvector::operator- (const GLvector& c)\r\n{\r\n  return glVector (x - c.x, y - c.y, z - c.z);\r\n}\r\n\r\nGLvector GLvector::operator- (const float& c)\r\n{\r\n  return glVector (x - c, y - c, z - c);\r\n}\r\n\r\nvoid GLvector::operator-= (const GLvector& c)\r\n{\r\n  x -= c.x;\r\n  y -= c.y;\r\n  z -= c.z;\r\n}\r\n\r\nvoid GLvector::operator-= (const float& c)\r\n{\r\n  x -= c;\r\n  y -= c;\r\n  z -= c;\r\n}\r\n\r\nGLvector GLvector::operator* (const GLvector& c)\r\n{\r\n  return glVector (x * c.x, y * c.y, z * c.z);\r\n}\r\n\r\nGLvector GLvector::operator* (const float& c)\r\n{\r\n  return glVector (x * c, y * c, z * c);\r\n}\r\n\r\nvoid GLvector::operator*= (const GLvector& c)\r\n{\r\n  x *= c.x;\r\n  y *= c.y;\r\n  z *= c.z;\r\n}\r\n\r\nvoid GLvector::operator*= (const float& c)\r\n{\r\n  x *= c;\r\n  y *= c;\r\n  z *= c;\r\n}\r\n\r\nGLvector GLvector::operator/ (const GLvector& c)\r\n{\r\n  return glVector (x / c.x, y / c.y, z / c.z);\r\n}\r\n\r\nGLvector GLvector::operator/ (const float& c)\r\n{\r\n  return glVector (x / c, y / c, z / c);\r\n}\r\n\r\nvoid GLvector::operator/= (const GLvector& c)\r\n{\r\n  x /= c.x;\r\n  y /= c.y;\r\n  z /= c.z;\r\n}\r\n\r\nvoid GLvector::operator/= (const float& c)\r\n{\r\n  x /= c;\r\n  y /= c;\r\n  z /= c;\r\n}\r\n\r\nbool GLvector::operator== (const GLvector& c)\r\n{\r\n  if (x == c.x && y == c.y && z == c.z)\r\n    return true;\r\n  return false;\r\n}"
  }
]