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

  Deco.cpp

  2009 Shamus Young

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

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

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

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

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

#include "glTypes.h"
#include "Deco.h"
#include "Light.h"
#include "Mesh.h"
#include "Macro.h"
#include "Random.h"
#include "Texture.h"


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

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

CDeco::~CDeco ()
{

  delete _mesh;

}

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

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

CDeco::CDeco ()
{

  _mesh = new CMesh ();
  _use_alpha = false;

}

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

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

void CDeco::Render ()
{

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

}

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

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

void CDeco::RenderFlat (bool colored)
{


}

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

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

bool CDeco::Alpha ()
{ 
  
  return _use_alpha; 

}


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

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

int CDeco::PolyCount ()
{

  return _mesh->PolyCount ();

}

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

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

unsigned CDeco::Texture ()
{

  return _texture;

}

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

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

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

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

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

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

}

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

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

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

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

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

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

}
#endif

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

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

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

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

}

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

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

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

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

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

}
