#include "basis.h"

static void Init(void );
static void CALLBACK Reshape(int width,int height);
static void CALLBACK Draw(void );
static void CALLBACK Key_1(void );
static void CALLBACK Key_2(void );
static void CALLBACK Key_3(void );
static void CALLBACK Key_4(void );

GLint windW, windH;
GLenum blend, order, depth, color;

static void Init(void)
{
  glClearColor(0.66f, 0.66f, 0.66f, 1.0f);

  glNewList(1, GL_COMPILE);
    glColor3f(0.9f, 1.0f, 0.0f);
    glBegin(GL_TRIANGLES);
      glVertex3i(-windW/4 + 30,  windH/2 - 20, 0);
      glVertex3i( windW/4 - 10,            0,  0);
      glVertex3i(-windW/4 + 30, -windH/2 + 20, 0);
    glEnd();
  glEndList();

  glNewList(2, GL_COMPILE);
    glColor3f(0.0f, 0.0f, 0.9f);
    glBegin(GL_TRIANGLES);
      glVertex3i( windW/4 - 30,  windH/2 - 20, -50);
      glVertex3i( windW/4 - 30, -windH/2 + 20, -10);
      glVertex3i(-windW/4 + 10,             0,  75);
    glEnd();
  glEndList();

  blend = GL_TRUE;
  order = GL_TRUE;
  depth = GL_TRUE;
  color = GL_TRUE;
}

static void CALLBACK Reshape(int width, int height)
{
  windW = (GLint)width;
  windH = (GLint)height;
}

static void CALLBACK Key_1(void)
{
  blend = !blend;
}

static void CALLBACK Key_2(void)
{
  order = !order;
}

static void CALLBACK Key_3(void)
{
  depth = !depth;
}

static void CALLBACK Key_4(void)
{
  color = !color;
}

static void CALLBACK DrawBorder(int left)
{
  GLint x;
  GLushort pattern;
  GLfloat width;

  glColor3f(0.0f, 0.0f, 0.0f);
  if(!left){
    pattern = 0x1C47;
    x = windW/4;
  }
  else{
    pattern = 0x471C;
    x = -windW/4;
  }
  glPushMatrix();
    glGetFloatv(GL_LINE_WIDTH, &width);
    glLineWidth(2.0f);
    glLineStipple(2, pattern);
    glEnable(GL_LINE_STIPPLE);
    glBegin(GL_LINES);
      glVertex2i(x, -windH/2);
      glVertex2i(x,  windH/2);
    glEnd();
    glDisable(GL_LINE_STIPPLE);
    glLineWidth(width);
  glPopMatrix();
}

static void CALLBACK InitViewport(int x, int y, int width, int height)
{
  glViewport(x, y, width, height);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-windW/4, windW/4, -windH/2, windH/2, -100, 100);
  glMatrixMode(GL_MODELVIEW);
}

static void CALLBACK DrawScene(GLenum mode)
{
  // Здесь вызываются команды рисования
  // ...

  if(!depth)
    glDepthMask(GL_FALSE);
  else
    glDepthMask(GL_TRUE);

  if(!color)
    glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
  else
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

  if(mode == GL_TRUE){
    glEnable(GL_DEPTH_TEST);
    if(blend)
      glEnable(GL_BLEND);
    else
      glDisable(GL_BLEND);
  }
  else{
    glDisable(GL_DEPTH_TEST);
  }

  if(order){
    glCallList(1);
    glCallList(2);
  }
  else{
    glCallList(2);
    glCallList(1);
  }

  glDisable(GL_BLEND);
}

static void CALLBACK Draw(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  
  InitViewport(0,0, windW/2, windH);
  DrawBorder(0);
  DrawScene(GL_FALSE);

  InitViewport(windW/2, 0, windW/2, windH);
  DrawBorder(1);
  DrawScene(GL_TRUE);

  glFinish();
  auxSwapBuffers();
}

void main(int argc, char **argv)
{
  windW = 400;
  windH = 300;
  auxInitPosition(200, 100, windW, windH);

  auxInitDisplayMode(AUX_RGB | AUX_DOUBLE);

  if (auxInitWindow("Работа с буфером глубины (z-буфером) ...") == GL_FALSE) {
    auxQuit();
  }

  Init();

  auxExposeFunc((AUXEXPOSEPROC)Reshape);
  auxReshapeFunc((AUXRESHAPEPROC)Reshape);
  auxKeyFunc(AUX_1, Key_1);
  auxKeyFunc(AUX_2, Key_2);
  auxKeyFunc(AUX_3, Key_3);
  auxKeyFunc(AUX_4, Key_4);
  auxMainLoop(Draw);
}
