/*
**	$VER: select.c 1.1 (12.03.1998)
**
**	This is an example program for CyberGL
**
**      Written by Frank Gerberding
**
**	Copyright © 1996-1998 by phase5 digital products
**      All Rights reserved.
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <clib/exec_protos.h>

#define CYBERGLNAME             "cybergl.library"
#define CYBERGLVERSION          39L


#define SHARED                  /* we use the cyberglshared library */
#define GL_APICOMPATIBLE        /* we use stubs from cybergl.lib */


#include <cybergl/cybergl.h>
#include <proto/cybergl.h>

#ifdef SHARED
LONG __oslibversion   = 39L;
LONG __CGLlibversion = CYBERGLVERSION;
#endif

#define WIDTH    600
#define HEIGHT   450
#define BUFSIZE 1000
#define RED        1
#define GREEN      2
#define BLUE       3
#define WHITE      4





void pointLight (GLdouble x,    GLdouble y,    GLdouble z,
                 GLdouble r,    GLdouble g,    GLdouble b,
                 GLdouble att0, GLdouble att1, GLdouble att2, GLenum light)
{
  GLfloat pos   [4];
  GLfloat color [4];

  pos   [0] = (GLfloat) x;
  pos   [1] = (GLfloat) y;
  pos   [2] = (GLfloat) z;
  pos   [3] = (GLfloat) 1.0;
  color [0] = (GLfloat) r;
  color [1] = (GLfloat) g;
  color [2] = (GLfloat) b;
  color [3] = (GLfloat) 0.0;

  glEnable  (GL_LIGHTING);
  glEnable  (light);
  glLightfv (light, GL_POSITION,              pos);
  glLightfv (light, GL_DIFFUSE,               color);
  glLightfv (light, GL_SPECULAR,              color);
  glLightf  (light, GL_CONSTANT_ATTENUATION,  (GLfloat) att0);
  glLightf  (light, GL_LINEAR_ATTENUATION,    (GLfloat) att1);
  glLightf  (light, GL_QUADRATIC_ATTENUATION, (GLfloat) att2);
}





void drawCube (void)
{
  glBegin (GL_QUADS);
    glNormal3d ( 0.0,  0.0,  1.0);
    glEdgeFlag (GL_TRUE);
    glVertex3d (-0.5, -0.5,  0.5);
    glVertex3d ( 0.5, -0.5,  0.5);
    glVertex3d ( 0.5,  0.5,  0.5);
    glVertex3d (-0.5,  0.5,  0.5);

    glNormal3d ( 1.0,  0.0,  0.0);
    glEdgeFlag (GL_TRUE);
    glVertex3d ( 0.5, -0.5,  0.5);
    glEdgeFlag (GL_FALSE);
    glVertex3d ( 0.5, -0.5, -0.5);
    glEdgeFlag (GL_TRUE);
    glVertex3d ( 0.5,  0.5, -0.5);
    glEdgeFlag (GL_FALSE);
    glVertex3d ( 0.5,  0.5,  0.5);

    glNormal3d ( 0.0,  0.0, -1.0);
    glEdgeFlag (GL_TRUE);
    glVertex3d ( 0.5, -0.5, -0.5);
    glVertex3d (-0.5, -0.5, -0.5);
    glVertex3d (-0.5,  0.5, -0.5);
    glVertex3d ( 0.5,  0.5, -0.5);

    glNormal3d (-1.0,  0.0,  0.0);
    glEdgeFlag (GL_TRUE);
    glVertex3d (-0.5, -0.5, -0.5);
    glEdgeFlag (GL_FALSE);
    glVertex3d (-0.5, -0.5,  0.5);
    glEdgeFlag (GL_TRUE);
    glVertex3d (-0.5,  0.5,  0.5);
    glEdgeFlag (GL_FALSE);
    glVertex3d (-0.5,  0.5, -0.5);

    glNormal3d ( 0.0,  1.0,  0.0);
    glVertex3d (-0.5,  0.5,  0.5);
    glVertex3d ( 0.5,  0.5,  0.5);
    glVertex3d ( 0.5,  0.5, -0.5);
    glVertex3d (-0.5,  0.5, -0.5);

    glNormal3d ( 0.0, -1.0,  0.0);
    glVertex3d (-0.5, -0.5, -0.5);
    glVertex3d ( 0.5, -0.5, -0.5);
    glVertex3d ( 0.5, -0.5,  0.5);
    glVertex3d (-0.5, -0.5,  0.5);
  glEnd ();
}





void drawCubes (void)
{
  glMatrixMode (GL_MODELVIEW);

  glInitNames ();

  glPushName (RED);

  glPushMatrix ();
  glTranslated (-1.0, -1.0, 0.0);
  glColor3d (1.0, 0.0, 0.0);
  drawCube ();
  glPopMatrix ();

  glLoadName (GREEN);

  glPushMatrix ();
  glTranslated (-1.0,  1.0, 0.0);
  glColor3d (0.0, 1.0, 0.0);
  drawCube ();
  glPopMatrix ();

  glLoadName (BLUE);

  glPushMatrix ();
  glTranslated ( 1.0,  1.0, 0.0);
  glColor3d (0.0, 0.0, 1.0);
  drawCube ();
  glPopMatrix ();

  glLoadName (WHITE);

  glPushMatrix ();
  glTranslated ( 1.0, -1.0, 0.0);
  glColor3d (1.0, 1.0, 1.0);
  drawCube ();
  glPopMatrix ();

  glPopName ();
}





void printBuffer (GLint num, GLuint buffer[])
{
  GLint count;
  GLint index;
  GLint remain;

  index = 0;

  for (count = 0; count < num; count++)
  {
    for (remain = buffer [index]; remain > 0; remain--)
    {
      switch (buffer [index + 2 + remain])
      {
        case RED:
          printf ("Roter  Würfel\n");
          break;
        case GREEN:
          printf ("Grüner Würfel\n");
          break;
        case BLUE:
          printf ("Blauer Würfel\n");
          break;
        case WHITE:
          printf ("Weißer Würfel\n");
          break;
      }
    }
    index += 3 + buffer [index];
  }
}





void handle_window_events (struct Window *window, GLuint *buffer)
{
  struct IntuiMessage *msg;
  int                  done = 0;

  while (!done)
  {
    Wait (1L << window->UserPort->mp_SigBit);
    while ((!done) && (msg = (struct IntuiMessage *) GetMsg (window->UserPort)))
    {
      switch (msg->Class)
      {
        case IDCMP_CLOSEWINDOW:
          done = 1;
          break;
        case IDCMP_MOUSEBUTTONS:
          if (msg->Code == SELECTDOWN)
          {
            glRenderMode   (GL_SELECT);
            glMatrixMode   (GL_PROJECTION);
            glLoadIdentity ();
            glPickMatrix   ((double) msg->MouseX - window->BorderLeft, (double) HEIGHT - (msg->MouseY - window->BorderTop - 1), 4.0, 4.0);
            glPerspective  (40.0, 1.333, 0.5, 50.5);
            drawCubes      ();
            printBuffer    (glRenderMode (GL_RENDER), buffer);
          }
          break;
      }
      ReplyMsg ((struct Message *) msg);
    }
  }
}





void main (int argc, char *argv[])
{
  void     *window;
  GLuint    buffer [BUFSIZE];

  window  = openGLWindowTags (WIDTH, HEIGHT, GLWA_Title, "Selection Mode",
                                             GLWA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_MOUSEBUTTONS,
                                             GLWA_CloseGadget, TRUE,
                                             GLWA_DepthGadget, TRUE,
                                             GLWA_DragBar,     TRUE,
                                             GLWA_Activate, TRUE,
                                             GLWA_RGBAMode, GL_TRUE,
                                             TAG_DONE);
  if (window)
  {
    glEnable         (GL_DITHER);
    glEnable         (GL_CULL_FACE);
    glColorMaterial  (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glEnable         (GL_COLOR_MATERIAL);
    glShadeModel     (GL_SMOOTH);
    glClear          (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glSelectBuffer   (BUFSIZE, buffer);
    glMatrixMode     (GL_PROJECTION);
    glPerspective    (40.0, 1.333, 0.5, 50.5);
    glMatrixMode     (GL_MODELVIEW);

#ifndef GL_APICOMPATIBLE
    {
     GLlookAt lookat;

     lookat.eyex    = 2.0;
     lookat.eyey    = 2.0;
     lookat.eyez    = 5.0;
     lookat.centerx = 0.0;
     lookat.centery = 0.0;
     lookat.centerz = 0.0;
     lookat.upx     = 0.0;
     lookat.upy     = 1.0;
     lookat.upz     = 0.0;
     glLookAt (&lookat);
    }
#else
    glLookAt         (2.0,  2.0, 5.0,   0.0, 0.0, 0.0,   0.0, 1.0, 0.0);
#endif

    pointLight  (5.0, 6.0, 10.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, GL_LIGHT0);
    drawCubes ();

    handle_window_events (getWindow (window), buffer);

    closeGLWindow (window);
  }
}
