/******************************************************************************
 *{@C
 *      Copyright:      2005-2018 Paul Obermeier (obermeier@tcl3d.org)
 *
 *                      See the file "Tcl3D_License.txt" for information on
 *                      usage and redistribution of this file, and for a
 *                      DISCLAIMER OF ALL WARRANTIES.
 *
 *      Module:         Tcl3D -> tcl3dOgl
 *      Filename:       tcl3dShapesMisc.c
 *
 *      Author:         Paul Obermeier
 *
 *      Description:    C functions for generating miscellaneous standard 
 *                      shapes. See also the GLUT shape functions.
 *                      Currently the following shapes are implemented:
 *                      tcl3dCube
 *                      tcl3dSphere
 *                      tcl3dHelix
 *                      tcl3dCameraModel
 *                      tcl3dTeapotModel
 *
 *****************************************************************************/

#if defined(WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <winnt.h>
#endif

#include <math.h>
#include <GL/glew.h>

#include "tcl3dVecMath.h"
#include "tcl3dShapesMisc.h"

/*
 * Draw a textured box with style "type". Type can be GL_QUADS or GL_LINE_LOOPS.
 * The box is specified by the lower-left and upper-right corners.
 */

void tcl3dBox (const float lowerLeft[3], const float upperRight[3], GLenum type)
{
    float llx = lowerLeft[0];
    float lly = lowerLeft[1];
    float llz = lowerLeft[2];
    float urx = upperRight[0];
    float ury = upperRight[1];
    float urz = upperRight[2];

    /* Front Face */
    glBegin (type);
    glNormal3f (0.0f, 0.0f, 0.5f);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (llx, lly, urz);
    glTexCoord2f (1.0f, 0.0f); glVertex3f (urx, lly, urz);
    glTexCoord2f (1.0f, 1.0f); glVertex3f (urx, ury, urz);
    glTexCoord2f (0.0f, 1.0f); glVertex3f (llx, ury, urz);
    glEnd ();
    /* Back Face */
    glBegin (type);
    glNormal3f (0.0f, 0.0f, -0.5f);
    glTexCoord2f (1.0f, 0.0f); glVertex3f (llx, lly, llz);
    glTexCoord2f (1.0f, 1.0f); glVertex3f (llx, ury, llz);
    glTexCoord2f (0.0f, 1.0f); glVertex3f (urx, ury, llz);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (urx, lly, llz);
    glEnd ();
    /* Top Face */
    glBegin (type);
    glNormal3f (0.0f, 0.5f, 0.0f);
    glTexCoord2f (0.0f, 1.0f); glVertex3f (llx, ury, llz);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (llx, ury, urz);
    glTexCoord2f (1.0f, 0.0f); glVertex3f (urx, ury, urz);
    glTexCoord2f (1.0f, 1.0f); glVertex3f (urx, ury, llz);
    glEnd ();
    /* Bottom Face */
    glBegin (type);
    glNormal3f (0.0f, -0.5f, 0.0f);
    glTexCoord2f (1.0f, 1.0f); glVertex3f (llx, lly, llz);
    glTexCoord2f (0.0f, 1.0f); glVertex3f (urx, lly, llz);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (urx, lly, urz);
    glTexCoord2f (1.0f, 0.0f); glVertex3f (llx, lly, urz);
    glEnd ();
    /* Right Face */
    glBegin (type);
    glNormal3f (0.5f, 0.0f, 0.0f);
    glTexCoord2f (1.0f, 0.0f); glVertex3f (urx, lly, llz);
    glTexCoord2f (1.0f, 1.0f); glVertex3f (urx, ury, llz);
    glTexCoord2f (0.0f, 1.0f); glVertex3f (urx, ury, urz);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (urx, lly, urz);
    glEnd ();
    /* Left Face */
    glBegin (type);
    glNormal3f (-0.5f, 0.0f, 0.0f);
    glTexCoord2f (0.0f, 0.0f); glVertex3f (llx, lly, llz);
    glTexCoord2f (1.0f, 0.0f); glVertex3f (llx, lly, urz);
    glTexCoord2f (1.0f, 1.0f); glVertex3f (llx, ury, urz);
    glTexCoord2f (0.0f, 1.0f); glVertex3f (llx, ury, llz);
    glEnd ();
}

/*
 * Draw a textured cube as 6 GL_QUADS.
 * The center of the cube is at (cx, cy, cz) and it's size is "size".
 */
void tcl3dCube (float cx, float cy, float cz, float size)
{
    float lowerLeft[3];
    float upperRight[3];

    lowerLeft[0]  = cx - 0.5 * size;
    lowerLeft[1]  = cy - 0.5 * size;
    lowerLeft[2]  = cz - 0.5 * size;
    upperRight[0] = cx + 0.5 * size;
    upperRight[1] = cy + 0.5 * size;
    upperRight[2] = cz + 0.5 * size;

    tcl3dBox (lowerLeft, upperRight, GL_QUADS);
}

/*
 * Create a sphere centered at cy, cx, cz with radius r, and 
 * precision p.
 * Based on a function written by Paul Bourke.
 * http://astronomy.swin.edu.au/~pbourke/opengl/sphere/
 */
void tcl3dSphere (float cx, float cy, float cz, float r, int p)
{
    int i, j;

    const float PI     = 3.14159265358979f;
    const float TWOPI  = 6.28318530717958f;
    const float PIDIV2 = 1.57079632679489f;

    float theta1 = 0.0;
    float theta2 = 0.0;
    float theta3 = 0.0;

    float ex = 0.0f;
    float ey = 0.0f;
    float ez = 0.0f;

    float px = 0.0f;
    float py = 0.0f;
    float pz = 0.0f;

    /* Disallow a negative number for radius. */
    if ( r < 0 ) {
        r = -r;
    }

    /* Disallow a negative number for precision. */
    if ( p < 0 ) {
        p = -p;
    }

    /* If the sphere is too small, just render a OpenGL point instead. */
    if ( p < 4 || r <= 0 ) {
        glBegin (GL_POINTS);
        glVertex3f (cx, cy, cz);
        glEnd ();
        return;
    }

    for (i=0; i<p/2; ++i) {
        theta1 = i * TWOPI / p - PIDIV2;
        theta2 = (i + 1) * TWOPI / p - PIDIV2;

        glBegin (GL_TRIANGLE_STRIP);
        for (j=0; j<=p; ++j) {
            theta3 = j * TWOPI / p;

            ex = cos(theta2) * cos(theta3);
            ey = sin(theta2);
            ez = cos(theta2) * sin(theta3);
            px = cx + r * ex;
            py = cy + r * ey;
            pz = cz + r * ez;

            glNormal3f (ex, ey, ez);
            glTexCoord2f (-(j/(float)p) , 2*(i+1)/(float)p);
            glVertex3f (px, py, pz);

            ex = cos(theta1) * cos(theta3);
            ey = sin(theta1);
            ez = cos(theta1) * sin(theta3);
            px = cx + r * ex;
            py = cy + r * ey;
            pz = cz + r * ez;

            glNormal3f (ex, ey, ez);
            glTexCoord2f (-(j/(float)p), 2*i/(float)p);
            glVertex3f (px, py, pz);
        }
        glEnd ();
    }
}

/*
 * Draw a helix.
 * This code is based on an excerpt of NeHe's tutorial lesson 36
 * written by Dario Corno.
 */
void tcl3dHelix ( float cx, float cy, float cz, float r, int twists ) {
    const float PI = 3.14159265358979f;
    float x, y, z;
    float phi, theta;
    float u, v;
    float vtx0[3], vtx1[3], vtx2[3], vtx3[3];
    float normal[3];

    glBegin (GL_QUADS);
    for (phi=0.0f; phi<=360.0f; phi+=20.0f) {
        for (theta=0.0f; theta<=360.0f*twists; theta+=20.0f) {
            /* Calculate angle of first point (0, 0) */
            v=(phi/180.0f*PI);
            u=(theta/180.0f*PI);

            /* Calculate position of first point */
            x=(cos(u)*(2.0f+cos(v)))*r;
            y=(sin(u)*(2.0f+cos(v)))*r;
            z=((( u-(2.0f*PI)) + sin(v) ) * r);

            /* Set value of first vertex */
            vtx0[0]=x;
            vtx0[1]=y;
            vtx0[2]=z;

            /* Calculate angle of second point (0, 20) */
            v=(phi/180.0f*PI);
            u=((theta+20)/180.0f*PI);

            /* Calculate position of 2nd point */
            x=(cos(u)*(2.0f+cos(v) ))*r;
            y=(sin(u)*(2.0f+cos(v) ))*r;
            z=((( u-(2.0f*PI)) + sin(v) ) * r);

            /* Set value of second vertex */
            vtx1[0]=x;
            vtx1[1]=y;
            vtx1[2]=z;

            /* Calculate angle of third point (20, 20) */
            v=((phi+20)/180.0f*PI);
            u=((theta+20)/180.0f*PI);

            /* Calculate position of third point */
            x=(cos(u)*(2.0f+cos(v) ))*r;
            y=(sin(u)*(2.0f+cos(v) ))*r;
            z=((( u-(2.0f*PI)) + sin(v) ) * r);

            /* Set value of third vertex */
            vtx2[0]=x;
            vtx2[1]=y;
            vtx2[2]=z;

            /* Calculate angle of fourth point (20, 0) */
            v=((phi+20)/180.0f*PI);
            u=((theta)/180.0f*PI);

            /* Calculate position of fourth point */
            x=(cos(u)*(2.0f+cos(v) ))*r;
            y=(sin(u)*(2.0f+cos(v) ))*r;
            z=((( u-(2.0f*PI)) + sin(v) ) * r);

            /* Set value of fourth vertex */
            vtx3[0]=x;
            vtx3[1]=y;
            vtx3[2]=z;

            /* Calculate the quad normal and set it. */
            tcl3dVec3fPlaneNormal (vtx0, vtx1, vtx2, normal);
            glNormal3f (normal[0], normal[1], normal[2]);

            /* Render The Quad */
            glVertex3f (vtx0[0] + cx, vtx0[1] + cy, vtx0[2] + cz);
            glVertex3f (vtx1[0] + cx, vtx1[1] + cy, vtx1[2] + cz);
            glVertex3f (vtx2[0] + cx, vtx2[1] + cy, vtx2[2] + cz);
            glVertex3f (vtx3[0] + cx, vtx3[1] + cy, vtx3[2] + cz);
        }
    }
    glEnd ();
}

/*
 * Draw a simple camera model consisting of 192 triangles.
 * Bounding box of geometry: (-0.5, -0.35, -0.3) to (0.5, 0.37, 0.3).
 * This code is based on an excerpt of Song Ho Ahn's (song.ahn@gmail.com)
 * OpenGL demos.
 */

#include "tcl3dShapesCameraData.h"

void tcl3dCameraModel (void)
{
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT, 0, cameraNormals);
    glVertexPointer(3, GL_FLOAT, 0, cameraVertices);

    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[0]);
    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[5]);
    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[10]);
    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[15]);
    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[20]);
    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, &cameraIndices[25]);
    glDrawElements(GL_TRIANGLE_STRIP, 39, GL_UNSIGNED_INT, &cameraIndices[30]);
    glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_INT, &cameraIndices[69]);
    glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_INT, &cameraIndices[113]);
    glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_INT, &cameraIndices[157]);
    glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_INT, &cameraIndices[201]);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
}

/*
 * Draw a teapot model consisting of 6320 polygons.
 * Bounding box of geometry: (-3, 0, -2) to (3.434, 3.15, 2).
 * This code is based on an excerpt of Song Ho Ahn's (song.ahn@gmail.com)
 * OpenGL demos.
 */

#include "tcl3dShapesTeapotData.h"

void tcl3dTeapotModel (void)
{
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);

    glNormalPointer(GL_FLOAT, 0, teapotNormals);
    glVertexPointer(3, GL_FLOAT, 0, teapotVertices);

    glDrawElements(GL_TRIANGLE_STRIP, 12, GL_UNSIGNED_SHORT, &teapotIndices[0]);
    glDrawElements(GL_TRIANGLE_STRIP, 78, GL_UNSIGNED_SHORT, &teapotIndices[12]);
    glDrawElements(GL_TRIANGLE_STRIP, 35, GL_UNSIGNED_SHORT, &teapotIndices[90]);
    glDrawElements(GL_TRIANGLE_STRIP, 70, GL_UNSIGNED_SHORT, &teapotIndices[125]);
    glDrawElements(GL_TRIANGLE_STRIP, 65, GL_UNSIGNED_SHORT, &teapotIndices[195]);
    glDrawElements(GL_TRIANGLE_STRIP, 37, GL_UNSIGNED_SHORT, &teapotIndices[260]);
    glDrawElements(GL_TRIANGLE_STRIP, 35, GL_UNSIGNED_SHORT, &teapotIndices[297]);
    glDrawElements(GL_TRIANGLE_STRIP, 32, GL_UNSIGNED_SHORT, &teapotIndices[332]);
    glDrawElements(GL_TRIANGLE_STRIP, 56, GL_UNSIGNED_SHORT, &teapotIndices[364]);
    glDrawElements(GL_TRIANGLE_STRIP, 45, GL_UNSIGNED_SHORT, &teapotIndices[420]);
    glDrawElements(GL_TRIANGLE_STRIP, 41, GL_UNSIGNED_SHORT, &teapotIndices[465]);
    glDrawElements(GL_TRIANGLE_STRIP, 37, GL_UNSIGNED_SHORT, &teapotIndices[506]);
    glDrawElements(GL_TRIANGLE_STRIP, 33, GL_UNSIGNED_SHORT, &teapotIndices[543]);
    glDrawElements(GL_TRIANGLE_STRIP, 29, GL_UNSIGNED_SHORT, &teapotIndices[576]);
    glDrawElements(GL_TRIANGLE_STRIP, 25, GL_UNSIGNED_SHORT, &teapotIndices[605]);
    glDrawElements(GL_TRIANGLE_STRIP, 21, GL_UNSIGNED_SHORT, &teapotIndices[630]);
    glDrawElements(GL_TRIANGLE_STRIP, 17, GL_UNSIGNED_SHORT, &teapotIndices[651]);
    glDrawElements(GL_TRIANGLE_STRIP, 13, GL_UNSIGNED_SHORT, &teapotIndices[668]);
    glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_SHORT, &teapotIndices[681]);
    glDrawElements(GL_TRIANGLE_STRIP, 27, GL_UNSIGNED_SHORT, &teapotIndices[690]);
    glDrawElements(GL_TRIANGLE_STRIP, 16, GL_UNSIGNED_SHORT, &teapotIndices[717]);
    glDrawElements(GL_TRIANGLE_STRIP, 22, GL_UNSIGNED_SHORT, &teapotIndices[733]);
    glDrawElements(GL_TRIANGLE_STRIP, 50, GL_UNSIGNED_SHORT, &teapotIndices[755]);
    glDrawElements(GL_TRIANGLE_STRIP, 42, GL_UNSIGNED_SHORT, &teapotIndices[805]);
    glDrawElements(GL_TRIANGLE_STRIP, 43, GL_UNSIGNED_SHORT, &teapotIndices[847]);
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, &teapotIndices[890]);
    glDrawElements(GL_TRIANGLE_STRIP, 143, GL_UNSIGNED_SHORT, &teapotIndices[894]);
    glDrawElements(GL_TRIANGLE_STRIP, 234, GL_UNSIGNED_SHORT, &teapotIndices[1037]);
    glDrawElements(GL_TRIANGLE_STRIP, 224, GL_UNSIGNED_SHORT, &teapotIndices[1271]);
    glDrawElements(GL_TRIANGLE_STRIP, 71, GL_UNSIGNED_SHORT, &teapotIndices[1495]);
    glDrawElements(GL_TRIANGLE_STRIP, 69, GL_UNSIGNED_SHORT, &teapotIndices[1566]);
    glDrawElements(GL_TRIANGLE_STRIP, 67, GL_UNSIGNED_SHORT, &teapotIndices[1635]);
    glDrawElements(GL_TRIANGLE_STRIP, 65, GL_UNSIGNED_SHORT, &teapotIndices[1702]);
    glDrawElements(GL_TRIANGLE_STRIP, 63, GL_UNSIGNED_SHORT, &teapotIndices[1767]);
    glDrawElements(GL_TRIANGLE_STRIP, 61, GL_UNSIGNED_SHORT, &teapotIndices[1830]);
    glDrawElements(GL_TRIANGLE_STRIP, 59, GL_UNSIGNED_SHORT, &teapotIndices[1891]);
    glDrawElements(GL_TRIANGLE_STRIP, 57, GL_UNSIGNED_SHORT, &teapotIndices[1950]);
    glDrawElements(GL_TRIANGLE_STRIP, 55, GL_UNSIGNED_SHORT, &teapotIndices[2007]);
    glDrawElements(GL_TRIANGLE_STRIP, 53, GL_UNSIGNED_SHORT, &teapotIndices[2062]);
    glDrawElements(GL_TRIANGLE_STRIP, 51, GL_UNSIGNED_SHORT, &teapotIndices[2115]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[2166]);
    glDrawElements(GL_TRIANGLE_STRIP, 50, GL_UNSIGNED_SHORT, &teapotIndices[2169]);
    glDrawElements(GL_TRIANGLE_STRIP, 48, GL_UNSIGNED_SHORT, &teapotIndices[2219]);
    glDrawElements(GL_TRIANGLE_STRIP, 46, GL_UNSIGNED_SHORT, &teapotIndices[2267]);
    glDrawElements(GL_TRIANGLE_STRIP, 44, GL_UNSIGNED_SHORT, &teapotIndices[2313]);
    glDrawElements(GL_TRIANGLE_STRIP, 42, GL_UNSIGNED_SHORT, &teapotIndices[2357]);
    glDrawElements(GL_TRIANGLE_STRIP, 40, GL_UNSIGNED_SHORT, &teapotIndices[2399]);
    glDrawElements(GL_TRIANGLE_STRIP, 38, GL_UNSIGNED_SHORT, &teapotIndices[2439]);
    glDrawElements(GL_TRIANGLE_STRIP, 36, GL_UNSIGNED_SHORT, &teapotIndices[2477]);
    glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, &teapotIndices[2513]);
    glDrawElements(GL_TRIANGLE_STRIP, 32, GL_UNSIGNED_SHORT, &teapotIndices[2547]);
    glDrawElements(GL_TRIANGLE_STRIP, 30, GL_UNSIGNED_SHORT, &teapotIndices[2579]);
    glDrawElements(GL_TRIANGLE_STRIP, 28, GL_UNSIGNED_SHORT, &teapotIndices[2609]);
    glDrawElements(GL_TRIANGLE_STRIP, 26, GL_UNSIGNED_SHORT, &teapotIndices[2637]);
    glDrawElements(GL_TRIANGLE_STRIP, 24, GL_UNSIGNED_SHORT, &teapotIndices[2663]);
    glDrawElements(GL_TRIANGLE_STRIP, 22, GL_UNSIGNED_SHORT, &teapotIndices[2687]);
    glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_SHORT, &teapotIndices[2709]);
    glDrawElements(GL_TRIANGLE_STRIP, 18, GL_UNSIGNED_SHORT, &teapotIndices[2729]);
    glDrawElements(GL_TRIANGLE_STRIP, 16, GL_UNSIGNED_SHORT, &teapotIndices[2747]);
    glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, &teapotIndices[2763]);
    glDrawElements(GL_TRIANGLE_STRIP, 12, GL_UNSIGNED_SHORT, &teapotIndices[2777]);
    glDrawElements(GL_TRIANGLE_STRIP, 10, GL_UNSIGNED_SHORT, &teapotIndices[2789]);
    glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, &teapotIndices[2799]);
    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, &teapotIndices[2807]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[2813]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[2816]);
    glDrawElements(GL_TRIANGLE_STRIP, 200, GL_UNSIGNED_SHORT, &teapotIndices[2819]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3019]);
    glDrawElements(GL_TRIANGLE_STRIP, 66, GL_UNSIGNED_SHORT, &teapotIndices[3022]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3088]);
    glDrawElements(GL_TRIANGLE_STRIP, 209, GL_UNSIGNED_SHORT, &teapotIndices[3091]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3300]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3303]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3306]);
    glDrawElements(GL_TRIANGLE_STRIP, 38, GL_UNSIGNED_SHORT, &teapotIndices[3309]);
    glDrawElements(GL_TRIANGLE_STRIP, 15, GL_UNSIGNED_SHORT, &teapotIndices[3347]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3362]);
    glDrawElements(GL_TRIANGLE_STRIP, 26, GL_UNSIGNED_SHORT, &teapotIndices[3365]);
    glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_SHORT, &teapotIndices[3391]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3400]);
    glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, &teapotIndices[3403]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3417]);
    glDrawElements(GL_TRIANGLE_STRIP, 115, GL_UNSIGNED_SHORT, &teapotIndices[3420]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3535]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3538]);
    glDrawElements(GL_TRIANGLE_STRIP, 39, GL_UNSIGNED_SHORT, &teapotIndices[3541]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3580]);
    glDrawElements(GL_TRIANGLE_STRIP, 91, GL_UNSIGNED_SHORT, &teapotIndices[3583]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3674]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3677]);
    glDrawElements(GL_TRIANGLE_STRIP, 31, GL_UNSIGNED_SHORT, &teapotIndices[3680]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3711]);
    glDrawElements(GL_TRIANGLE_STRIP, 67, GL_UNSIGNED_SHORT, &teapotIndices[3714]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3781]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3784]);
    glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_SHORT, &teapotIndices[3787]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3810]);
    glDrawElements(GL_TRIANGLE_STRIP, 45, GL_UNSIGNED_SHORT, &teapotIndices[3813]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3858]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3861]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3864]);
    glDrawElements(GL_TRIANGLE_STRIP, 32, GL_UNSIGNED_SHORT, &teapotIndices[3867]);
    glDrawElements(GL_TRIANGLE_STRIP, 38, GL_UNSIGNED_SHORT, &teapotIndices[3899]);
    glDrawElements(GL_TRIANGLE_STRIP, 15, GL_UNSIGNED_SHORT, &teapotIndices[3937]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3952]);
    glDrawElements(GL_TRIANGLE_STRIP, 26, GL_UNSIGNED_SHORT, &teapotIndices[3955]);
    glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_SHORT, &teapotIndices[3981]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[3990]);
    glDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_SHORT, &teapotIndices[3993]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[4007]);
    glDrawElements(GL_TRIANGLE_STRIP, 135, GL_UNSIGNED_SHORT, &teapotIndices[4010]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[4145]);
    glDrawElements(GL_TRIANGLE_STRIP, 76, GL_UNSIGNED_SHORT, &teapotIndices[4148]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[4224]);
    glDrawElements(GL_TRIANGLE_STRIP, 60, GL_UNSIGNED_SHORT, &teapotIndices[4227]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[4287]);
    glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_SHORT, &teapotIndices[4290]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[4313]);
    glDrawElements(GL_TRIANGLE_STRIP, 26, GL_UNSIGNED_SHORT, &teapotIndices[4316]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[4342]);
    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, &teapotIndices[4345]);
    glDrawElements(GL_TRIANGLE_STRIP, 947, GL_UNSIGNED_SHORT, &teapotIndices[4351]);
    glDrawElements(GL_TRIANGLE_STRIP, 35, GL_UNSIGNED_SHORT, &teapotIndices[5298]);
    glDrawElements(GL_TRIANGLE_STRIP, 31, GL_UNSIGNED_SHORT, &teapotIndices[5333]);
    glDrawElements(GL_TRIANGLE_STRIP, 27, GL_UNSIGNED_SHORT, &teapotIndices[5364]);
    glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_SHORT, &teapotIndices[5391]);
    glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_SHORT, &teapotIndices[5414]);
    glDrawElements(GL_TRIANGLE_STRIP, 24, GL_UNSIGNED_SHORT, &teapotIndices[5434]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5458]);
    glDrawElements(GL_TRIANGLE_STRIP, 28, GL_UNSIGNED_SHORT, &teapotIndices[5461]);
    glDrawElements(GL_TRIANGLE_STRIP, 32, GL_UNSIGNED_SHORT, &teapotIndices[5489]);
    glDrawElements(GL_TRIANGLE_STRIP, 36, GL_UNSIGNED_SHORT, &teapotIndices[5521]);
    glDrawElements(GL_TRIANGLE_STRIP, 76, GL_UNSIGNED_SHORT, &teapotIndices[5557]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5633]);
    glDrawElements(GL_TRIANGLE_STRIP, 67, GL_UNSIGNED_SHORT, &teapotIndices[5636]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5703]);
    glDrawElements(GL_TRIANGLE_STRIP, 59, GL_UNSIGNED_SHORT, &teapotIndices[5706]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5765]);
    glDrawElements(GL_TRIANGLE_STRIP, 51, GL_UNSIGNED_SHORT, &teapotIndices[5768]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5819]);
    glDrawElements(GL_TRIANGLE_STRIP, 43, GL_UNSIGNED_SHORT, &teapotIndices[5822]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5865]);
    glDrawElements(GL_TRIANGLE_STRIP, 35, GL_UNSIGNED_SHORT, &teapotIndices[5868]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5903]);
    glDrawElements(GL_TRIANGLE_STRIP, 27, GL_UNSIGNED_SHORT, &teapotIndices[5906]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5933]);
    glDrawElements(GL_TRIANGLE_STRIP, 19, GL_UNSIGNED_SHORT, &teapotIndices[5936]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5955]);
    glDrawElements(GL_TRIANGLE_STRIP, 11, GL_UNSIGNED_SHORT, &teapotIndices[5958]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[5969]);
    glDrawElements(GL_TRIANGLE_STRIP, 30, GL_UNSIGNED_SHORT, &teapotIndices[5972]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[6002]);
    glDrawElements(GL_TRIANGLE_STRIP, 11, GL_UNSIGNED_SHORT, &teapotIndices[6005]);
    glDrawElements(GL_TRIANGLE_STRIP, 18, GL_UNSIGNED_SHORT, &teapotIndices[6016]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[6034]);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &teapotIndices[6037]);
    glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, &teapotIndices[6040]);
    glDrawElements(GL_TRIANGLE_STRIP, 122, GL_UNSIGNED_SHORT, &teapotIndices[6045]);
    glDrawElements(GL_TRIANGLE_STRIP, 75, GL_UNSIGNED_SHORT, &teapotIndices[6167]);
    glDrawElements(GL_TRIANGLE_STRIP, 71, GL_UNSIGNED_SHORT, &teapotIndices[6242]);
    glDrawElements(GL_TRIANGLE_STRIP, 67, GL_UNSIGNED_SHORT, &teapotIndices[6313]);
    glDrawElements(GL_TRIANGLE_STRIP, 63, GL_UNSIGNED_SHORT, &teapotIndices[6380]);
    glDrawElements(GL_TRIANGLE_STRIP, 59, GL_UNSIGNED_SHORT, &teapotIndices[6443]);
    glDrawElements(GL_TRIANGLE_STRIP, 55, GL_UNSIGNED_SHORT, &teapotIndices[6502]);
    glDrawElements(GL_TRIANGLE_STRIP, 51, GL_UNSIGNED_SHORT, &teapotIndices[6557]);
    glDrawElements(GL_TRIANGLE_STRIP, 47, GL_UNSIGNED_SHORT, &teapotIndices[6608]);
    glDrawElements(GL_TRIANGLE_STRIP, 43, GL_UNSIGNED_SHORT, &teapotIndices[6655]);
    glDrawElements(GL_TRIANGLE_STRIP, 39, GL_UNSIGNED_SHORT, &teapotIndices[6698]);
    glDrawElements(GL_TRIANGLE_STRIP, 35, GL_UNSIGNED_SHORT, &teapotIndices[6737]);
    glDrawElements(GL_TRIANGLE_STRIP, 31, GL_UNSIGNED_SHORT, &teapotIndices[6772]);
    glDrawElements(GL_TRIANGLE_STRIP, 27, GL_UNSIGNED_SHORT, &teapotIndices[6803]);
    glDrawElements(GL_TRIANGLE_STRIP, 23, GL_UNSIGNED_SHORT, &teapotIndices[6830]);
    glDrawElements(GL_TRIANGLE_STRIP, 19, GL_UNSIGNED_SHORT, &teapotIndices[6853]);
    glDrawElements(GL_TRIANGLE_STRIP, 15, GL_UNSIGNED_SHORT, &teapotIndices[6872]);
    glDrawElements(GL_TRIANGLE_STRIP, 11, GL_UNSIGNED_SHORT, &teapotIndices[6887]);
    glDrawElements(GL_TRIANGLE_STRIP, 7, GL_UNSIGNED_SHORT, &teapotIndices[6898]);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
}
