/*
**	$VER: hsv.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 cybergl shared 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








static void hsv_to_rgb (double h, double s, double v, double *r, double *g, double *b)
{
  double f, p, q, t;
  int    i;

  if (s == 0.0)
  {
    *r = v;
    *g = v;
    *b = v;
  }
  else
  {
    h = h == 360.0 ? 0.0 : h / 60.0;
    i = h;
    f = h - i;
    p = v * (1.0 - s);
    q = v * (1.0 - (s * f));
    t = v * (1.0 - (s * (1.0 - f)));
    switch (i)
    {
      case 0: *r = v; *g = t; *b = p; break;
      case 1: *r = q; *g = v; *b = p; break;
      case 2: *r = p; *g = v; *b = t; break;
      case 3: *r = p; *g = q; *b = v; break;
      case 4: *r = t; *g = p; *b = v; break;
      case 5: *r = v; *g = p; *b = q; break;
    }
  }
}





void draw_HSV_disk (double v, int stepnum)
{
  double angle;
  double step;
  double r, g, b;

/*
  GLdouble plane [] = {-1.0, -1.0, 1.0,  -0.5};

  glClipPlane (GL_CLIP_PLANE0, plane);
  glEnable    (GL_CLIP_PLANE0);
*/

  glMatrixMode   (GL_PROJECTION);
  glLoadIdentity ();
  glOrtho2D      (-1.33333, 1.33333, -1.0, 1.0);

  step = 360.0 / (double) stepnum;
  for (angle = 0.0; angle <= 360.1 - step; angle += step)
  {
    glBegin (GL_TRIANGLES);
      hsv_to_rgb (angle, 1.0, v, &r, &g, &b);
      glColor3d  (r, g, b);
      glVertex2d (cos (angle * 3.14159265 / 180.0), sin (angle * 3.14159265 / 180.0));

      hsv_to_rgb (angle + step, 1.0, v, &r, &g, &b);
      glColor3d  (r, g, b);
      glVertex2d (cos ((angle + step + 0.00001) * 3.14159265 / 180.0), sin ((angle + step + 0.00001) * 3.14159265 / 180.0));

      hsv_to_rgb (0.0, 0.0, v, &r, &g, &b);
      glColor3d  (r, g, b);
      glVertex2d (0.0, 0.0);
    glEnd ();
  }
}




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

  window = getWindow (win);

  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_NEWSIZE:
          resizeGLWindow   (win, window->GZZWidth, window->GZZHeight);
          glClear          (GL_COLOR_BUFFER_BIT);
          draw_HSV_disk    (1.0, 50);
          break;
      }
      ReplyMsg ((struct Message *) msg);
    }
  }
}




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

  window  = openGLWindowTags (WIDTH, HEIGHT, GLWA_Title, "HSV Disk",
                                             GLWA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_NEWSIZE,
                                             GLWA_CloseGadget, TRUE,
                                             GLWA_DepthGadget, TRUE,
                                             GLWA_DragBar,     TRUE,
                                             GLWA_Activate, TRUE,
                                             GLWA_RGBAMode, GL_TRUE,
                                             GLWA_SizeGadget, TRUE,
                                             GLWA_MaxWidth, 1280,
                                             GLWA_MaxHeight, 1024,
                                             TAG_DONE);
  if (window)
  {
    glEnable         (GL_DITHER);
    glShadeModel     (GL_SMOOTH);
    glClear          (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    draw_HSV_disk    (1.0, 50);

    handle_window_events (window);

    closeGLWindow (window);
  }
}
