/*
 * PVVMUD a 3D MUD
 * Copyright (C) 1998-1999  Programvareverkstedet (pvv@pvv.org)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "pvvmud.H"
#include "glgeometry.H"


/*******************************************************************************
 * 
 * Constructor for ObjectGeometry 
 *
 ******************************************************************************/

CGLGeometry::CGLGeometry( int objectGeometryId )
            :CGeometry( objectGeometryId )
{
  
}

CGLGeometry::CGLGeometry( int objectGeometryId, int numVertices, 
                          int numNormals, int numTexCoords, int numPolygons )
            :CGeometry( objectGeometryId, numVertices, numNormals,
                        numTexCoords, numPolygons)
{
  
}

/*******************************************************************************
 * 
 * Destructor for ObjectGeometry 
 *
 ******************************************************************************/
CGLGeometry::~CGLGeometry(){
}


/*******************************************************************************
 * 
 * Draw ObjectGeometry 
 *
 ******************************************************************************/

int CGLGeometry::draw( CMaterialCache * matCache,
			 CTextureCache * texCache ){

  int pp,ii;
  CPolygon * polygon;
  CIntArray *normalIndex,*vertexIndex,*texCoordIndex;
  int numVertex, numNormal, numTexCoord;
  //  CNormal * normal;
  //  CVertex * vertex;
  //  CTexCoord * texCoord;
  CMaterial * mat;
  
  for (pp = 0; pp < this->polygonList->getNumElements(); pp ++){

     polygon = this->polygonList->get( pp );
     numVertex = polygon->getVertexIList()->getNumElements();
     numNormal = polygon->getNormalIList()->getNumElements();
     numTexCoord = polygon->getTexCoordIList()->getNumElements();
     mat = matCache->get( polygon->getMaterial() );
     if (mat == NULL){
       mat = matCache->get( 0 );
//       cdebug(stderr,"Using default material %i for object %i\n",polygon->getMaterial(),id);
     }
     if (mat != NULL) mat->exec( texCache );
//       else cdebug(stderr,"Failed to find material!\n");
     
     vertexIndex = polygon->getVertexIList();//->getIndex();
     normalIndex = polygon->getNormalIList();//->getIndex();
     texCoordIndex = polygon->getTexCoordIList();//->getIndex();
     //vertex = this->vertexList->getVertex();
     //normal = this->normalList->getNormal();
     //texCoord = this->texCoordList->getTexCoord();

     glBegin( (GLenum)polygon->getType() );

     switch ( polygon->getType() ){
     case POLYGON_POLYGON:
     case POLYGON_QUAD_STRIP:
     case POLYGON_TRIANGLE_STRIP:
     case POLYGON_TRIANGLE_FAN:



       if (numVertex == numNormal) {
	 // One normal for each vertex 	 
	 if (numVertex == numTexCoord){
	   // Texture Coordinates 
	   for (ii = 0; ii < numVertex; ii++){
	     glNormal3dv(normalList->get(normalIndex->get(ii)));
	     glTexCoord2dv(texCoordList->get(texCoordIndex->get(ii)));
	     glVertex3dv(vertexList->get(texCoordIndex->get(ii)));
	   }
	 } else {
	   // No texture coordinates 
	   for (ii = 0; ii < numVertex; ii++){
	     glNormal3dv(normalList->get(normalIndex->get(ii)));
	     glVertex3dv(vertexList->get(texCoordIndex->get(ii)));
	   }
	 }
       } else {
	 // One normal for object 
	 if (numVertex == numTexCoord){
	   // Texture Coordinates 
	   glNormal3dv(normalList->get(0));
	   for (ii = 0; ii < numVertex; ii++){
	     glTexCoord2dv(texCoordList->get(texCoordIndex->get(ii)));
	     glVertex3dv(vertexList->get(texCoordIndex->get(ii)));
	   }	   
	 } else { 
	   // No texture coordinates 
	   glNormal3dv(normalList->get(0));
	   for (ii = 0; ii < numVertex; ii++){
	     glVertex3dv(vertexList->get(texCoordIndex->get(ii)));
	   }
	 }
       }
       break;

     case POLYGON_QUADS:

       if (numVertex == numNormal) {
	 // One normal for each vertex 
	 if (numNormal == numTexCoord){
	   // Texture Coordinates 
	   for (ii = 0; ii < numVertex; ii++){
	     glNormal3dv(normalList->get(normalIndex->get(ii)));
	     glTexCoord2dv(texCoordList->get(normalIndex->get(ii)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 } else {
	   for (ii = 0; ii < numVertex; ii++){
	     glNormal3dv(normalList->get(normalIndex->get(ii)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 }
       } else {
	 // One normal for each quad 
	 if (numVertex == numTexCoord){
	   // Texture Coordinates 
	   for (ii = 0; ii < numVertex; ii++){
	     if (ii%4 == 0) glNormal3dv(normalList->get(normalIndex->get(ii/4)));
	     glTexCoord2dv(texCoordList->get(texCoordIndex->get(ii)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 } else {
	   for (ii = 0; ii < numVertex; ii++){
	     if (ii%4 == 0) glNormal3dv(normalList->get(normalIndex->get(ii/4)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 }
       }
       break;

     case POLYGON_TRIANGLES:

       if (numVertex == numNormal) {
	 // One normal for each vertex 
	 if (numVertex == numTexCoord){
	   // Texture Coordinates 
	   for (ii = 0; ii < numVertex; ii++){
	     glNormal3dv(normalList->get(normalIndex->get(ii)));
	     glTexCoord2dv(texCoordList->get(texCoordIndex->get(ii)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 } else {
	   for (ii = 0; ii < numVertex; ii++){
	     glNormal3dv(normalList->get(normalIndex->get(ii)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 }
       } else {
	 // One normal for each triangle 
	 if (numVertex == numNormal){
	   // Texture Coordinates
	   for (ii = 0; ii < numVertex; ii++){
	     if (ii%3 == 0) glNormal3dv(normalList->get(normalIndex->get(ii/3)));
	     glTexCoord2dv(texCoordList->get(texCoordIndex->get(ii)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 } else {
	   for (ii = 0; ii < numVertex; ii++){
	     if (ii%3 == 0) glNormal3dv(normalList->get(normalIndex->get(ii/3)));
	     glVertex3dv(vertexList->get(vertexIndex->get(ii)));
	   }
	 }
       }
       break;

     }
     glEnd( );

  }

  if (next != NULL) {
    next->draw( matCache, texCache );
  }
  

  return TRUE;
}