/*
 * freeglut_teapot.c
 *
 * Teapot(tm) rendering code.
 *
 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
 * Creation date: Fri Dec 24 1999
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Original teapot code copyright follows:
 */

/*
 * (c) Copyright 1993, Silicon Graphics, Inc.
 *
 * ALL RIGHTS RESERVED
 *
 * Permission to use, copy, modify, and distribute this software
 * for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that
 * both the copyright notice and this permission notice appear in
 * supporting documentation, and that the name of Silicon
 * Graphics, Inc. not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.
 *
 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
 * "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
 * OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO
 * EVENT SHALL SILICON GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE
 * ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
 * INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
 * SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
 * NOT SILICON GRAPHICS, INC.  HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * US Government Users Restricted Rights
 *
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
 * (c)(1)(ii) of the Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 and/or in similar or
 * successor clauses in the FAR or the DOD or NASA FAR
 * Supplement.  Unpublished-- rights reserved under the copyright
 * laws of the United States.  Contractor/manufacturer is Silicon
 * Graphics, Inc., 2011 N.  Shoreline Blvd., Mountain View, CA
 * 94039-7311.
 *
 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
 */

#include <GL/glut.h>
#include "glut_internal.h"
#include "glut_teapot_data.h"

#define glBegin glctx->GLBegin
#define glEnd glctx->GLEnd
#define glEnable(cap) glctx->SetState(cap, GL_TRUE);
#define glMap2d glctx->GLMap2d
#define glMapGrid2d(nu, u1, u2, nv, v1, v2) \
			 glctx->GLMapGrid2f(nu, (GLfloat)u1, (GLfloat)u2, nv, (GLfloat)v1, (GLfloat)v2)
#define glEvalMesh2 glctx->GLEvalMesh2

#define glPushAttrib glctx->GLPushAttrib
#define glPushMatrix glctx->GLPushMatrix
#define glRotated(angle, x, y, z) glctx->GLRotatef((GLfloat)angle, (GLfloat)x, (GLfloat)y, (GLfloat) z)
#define glScaled(x, y, z) glctx->GLScalef((GLfloat)x, (GLfloat)y, (GLfloat)z)
#define glTranslated(x, y, z) glctx->GLTranslatef((GLfloat)x, (GLfloat)y, (GLfloat)z)
#define glPopAttrib glctx->GLPopAttrib
#define glPopMatrix glctx->GLPopMatrix

/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */


static void fghTeapot(struct GlutIFace *Self, GLint grid, GLdouble scale, GLenum type )
{
    GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self);
    struct GLContextIFace *glctx = ctx->__glutContext;
#if TARGET_HOST_WINCE
		int i, numV=sizeof(strip_vertices)/4, numI=sizeof(strip_normals)/4;
#else
    double p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
    long i, j, k, l;
#endif

    glPushAttrib( GL_ENABLE_BIT | GL_EVAL_BIT );
    glEnable( GL_AUTO_NORMAL );
    glEnable( GL_NORMALIZE );
    glEnable( GL_MAP2_VERTEX_3 );
    glEnable( GL_MAP2_TEXTURE_COORD_2 );

    glPushMatrix();
    glRotated( 270.0, 1.0, 0.0, 0.0 );
    glScaled( 0.5 * scale, 0.5 * scale, 0.5 * scale );
    glTranslated( 0.0, 0.0, -1.5 );

#if TARGET_HOST_WINCE
    glRotated( 90.0, 1.0, 0.0, 0.0 );
    glBegin( GL_TRIANGLE_STRIP );

    for( i = 0; i < numV-1; i++ )
    {
        int vidx = strip_vertices[i],
            nidx = strip_normals[i];

        if( vidx != -1 )
        {
            glNormal3fv( normals[nidx]  );
            glVertex3fv( vertices[vidx] );
        }
        else
        {
            glEnd();
            glBegin( GL_TRIANGLE_STRIP );
        }
    }

    glEnd();
#else
    for (i = 0; i < 10; i++) {
      for (j = 0; j < 4; j++) {
        for (k = 0; k < 4; k++) {
          for (l = 0; l < 3; l++) {
            p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
            q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
            if (l == 1)
              q[j][k][l] *= -1.0;
            if (i < 6) {
              r[j][k][l] =
                cpdata[patchdata[i][j * 4 + (3 - k)]][l];
              if (l == 0)
                r[j][k][l] *= -1.0;
              s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
              if (l == 0)
                s[j][k][l] *= -1.0;
              if (l == 1)
                s[j][k][l] *= -1.0;
            }
          }
        }
      }

      glMap2d(GL_MAP2_TEXTURE_COORD_2, 0.0, 1.0, 2, 2, 0.0, 1.0, 4, 2,
        &tex[0][0][0]);
      glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
        &p[0][0][0]);
      glMapGrid2d(grid, 0.0, 1.0, grid, 0.0, 1.0);
      glEvalMesh2(type, 0, grid, 0, grid);
      glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
        &q[0][0][0]);
      glEvalMesh2(type, 0, grid, 0, grid);
      if (i < 6) {
        glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
          &r[0][0][0]);
        glEvalMesh2(type, 0, grid, 0, grid);
        glMap2d(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 4, 0.0, 1.0, 12, 4,
          &s[0][0][0]);
        glEvalMesh2(type, 0, grid, 0, grid);
      }
    }
#endif  /* TARGET_HOST_WINCE */

    glPopMatrix();
    glPopAttrib();
}


/* -- INTERFACE FUNCTIONS -------------------------------------------------- */

/*
 * Renders a beautiful wired teapot...
 */
void glut_GLUTWireTeapot(struct GlutIFace *Self, GLdouble size )
{
    GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self);
    FREEGLUT_EXIT_IF_NOT_INITIALISED_NR( "glutWireTeapot" );
    /* We will use the general teapot rendering code */
	fghTeapot(Self, 10, size, GL_LINE );
}

/*
 * Renders a beautiful filled teapot...
 */
void glut_GLUTSolidTeapot(struct GlutIFace *Self, GLdouble size )
{
    GLUTcontext ctx = (GLUTcontext)GET_INSTANCE(Self);
    FREEGLUT_EXIT_IF_NOT_INITIALISED_NR( "glutSolidTeapot" );
    /* We will use the general teapot rendering code */
	fghTeapot(Self, 7, size, GL_FILL );
}

/*** END OF FILE ***/





