#!/usr/bin/env lablglut

(* Ported to lablglut by Issac Trotts on Wed Sep 18 19:26:06 MDT 2002. *)

open Printf

(* Copyright (c) Mark J. Kilgard  1994  1997.  *)

(* This program is freely distributable without licensing fees 
   and is provided without guarantee or warrantee expressed or 
   implied. This program is -not- in the public domain. *)

typedef enum {
  RESERVED  BODY_SIDE  BODY_EDGE  BODY_WHOLE  ARM_SIDE  ARM_EDGE  ARM_WHOLE 
  LEG_SIDE  LEG_EDGE  LEG_WHOLE  EYE_SIDE  EYE_EDGE  EYE_WHOLE  DINOSAUR
} displayLists;

(* *INDENT-OFF* *)
static GLfloat body[].(2) = { {0  3}  {1  1}  {5  1}  {8  4}  {10  4}  {11  5} 
  {11  11.5}  {13  12}  {13  13}  {10  13.5}  {13  14}  {13  15}  {11  16} 
  {8  16}  {7  15}  {7  13}  {8  12}  {7  11}  {6  6}  {4  3}  {3  2} 
  {1  2} };
static GLfloat arm[].(2) = { {8  10}  {9  9}  {10  9}  {13  8}  {14  9}  {16  9} 
  {15  9.5}  {16  10}  {15  10}  {15.5  11}  {14.5  10}  {14  11}  {14  10} 
  {13  9}  {11  11}  {9  11} };
static GLfloat leg[].(2) = { {8  6}  {8  4}  {9  3}  {9  2}  {8  1}  {8  0.5}  {9  0} 
  {12  0}  {10  1}  {10  2}  {12  4}  {11  6}  {10  7}  {9  7} };
static GLfloat eye[].(2) = { {8.75  15}  {9  14.7}  {9.6  14.7}  {10.1  15} 
  {9.6  15.25}  {9  15.25} };
static GLfloat skinColor[] = {0.1  1.0  0.1  1.0}  eyeColor[] = {1.0  0.2  0.2  1.0};
(* *INDENT-ON* *)

static void
extrudeSolidFromPolygon(GLfloat data[].(2)  unsigned int dataSize 
  GLdouble thickness  GLuint side  GLuint edge  GLuint whole)
  static GLUtriangulatorObj *tobj = NULL;
  GLdouble vertex.(3)  dx  dy  len;
  int i;
  int count = (int) (dataSize / (2 * sizeof(GLfloat)));

  if (tobj = NULL) then
    tobj = gluNewTess();  (* create and initialize a GLU
                             polygon tesselation object *)
    gluTessCallback(tobj  GLU_BEGIN  glBegin);
    gluTessCallback(tobj  GLU_VERTEX  glVertex2fv);  (* semi-tricky *)
    gluTessCallback(tobj  GLU_END  glEnd);
  glNewList(side  GL_COMPILE);
  glShadeModel(GL_SMOOTH);  (* smooth minimizes seeing
                               tessellation *)
  gluBeginPolygon(tobj);
  incr for (i = 0; i < count; i) {
    vertex.(0) = data.(i).(0);
    vertex.(1) = data.(i).(1);
    vertex.(2) = 0;
    gluTessVertex(tobj  vertex  data.(i));
  gluEndPolygon(tobj);
  glEndList();
  glNewList(edge  GL_COMPILE);
  glShadeModel(GL_FLAT);  (* flat shade keeps angular hands
                             from being "smoothed" *)
  glBegin(GL_QUAD_STRIP);
  incr for (i = 0; i <= count; i) {
    (* mod function handles closing the edge *)
    glVertex3f(data.(i % count).(0)  data.(i % count).(1)  0.0);
    glVertex3f(data.(i % count).(0)  data.(i % count).(1)  thickness);
    (* Calculate a unit normal by dividing by Euclidean
       distance. We * could be lazy and use
       glEnable(GL_NORMALIZE) so we could pass in * arbitrary
       normals for a very slight performance hit. *)
    dx = data.((i + 1) % count).(1) - data.(i % count).(1);
    dy = data.(i % count).(0) - data.((i + 1) % count).(0);
    len = sqrt(dx * dx + dy * dy);
    glNormal3f(dx / len  dy / len  0.0);
  glEnd();
  glEndList();
  glNewList(whole  GL_COMPILE);
  glFrontFace(GL_CW);
  glCallList(edge);
  glNormal3f(0.0  0.0  -1.0);  (* constant normal for side *)
  glCallList(side);
  glPushMatrix();
  glTranslatef(0.0  0.0  thickness);
  glFrontFace(GL_CCW);
  glNormal3f(0.0  0.0  1.0);  (* opposite normal for other side *)
  glCallList(side);
  glPopMatrix();
  glEndList();
  ;;

int
makeDinosaur(void)
  GLfloat bodyWidth = 3.0;

  extrudeSolidFromPolygon(body  sizeof(body)  bodyWidth 
    BODY_SIDE  BODY_EDGE  BODY_WHOLE);
  extrudeSolidFromPolygon(arm  sizeof(arm)  bodyWidth / 4 
    ARM_SIDE  ARM_EDGE  ARM_WHOLE);
  extrudeSolidFromPolygon(leg  sizeof(leg)  bodyWidth / 2 
    LEG_SIDE  LEG_EDGE  LEG_WHOLE);
  extrudeSolidFromPolygon(eye  sizeof(eye)  bodyWidth + 0.2 
    EYE_SIDE  EYE_EDGE  EYE_WHOLE);
  glNewList(DINOSAUR  GL_COMPILE);
  glPushMatrix();
  glTranslatef(-8  -8  -bodyWidth / 2);
  glMaterialfv(GL_FRONT  GL_DIFFUSE  skinColor);
  glCallList(BODY_WHOLE);
  glPushMatrix();
  glTranslatef(0.0  0.0  bodyWidth);
  glCallList(ARM_WHOLE);
  glCallList(LEG_WHOLE);
  glTranslatef(0.0  0.0  -bodyWidth - bodyWidth / 4);
  glCallList(ARM_WHOLE);
  glTranslatef(0.0  0.0  -bodyWidth / 4);
  glCallList(LEG_WHOLE);
  glTranslatef(0.0  0.0  bodyWidth / 2 - 0.1);
  glMaterialfv(GL_FRONT  GL_DIFFUSE  eyeColor);
  glCallList(EYE_WHOLE);
  glPopMatrix();
  glPopMatrix();
  glEndList();
  return DINOSAUR;
  ;;
let _ = main();;
