#include "models.h"
#include "ppmreader.h"

#include <stdio.h>


/**
 * Constants for number of textures for all models
 */
#define N_TEXTURES_TABLE       5
#define N_TEXTURES_RAFT        5
#define N_TEXTURES_BOAT        6
#define N_TEXTURES_SUBMARINE   7
#define N_TEXTURES_VESSEL      9
#define N_TEXTURES_SUN         2
#define N_TEXTURES_MOON        1


/* Table textures' enumeration */
enum texturesTable {
  TT_BASE     = 0,
  TT_OCEAN    = 1,
  TT_FOUND    = 2,
  TT_MISSED   = 3,
  TT_SELECTED = 4,
};

/* Table textures' files */
char * vpcTexturesNamesTable[N_TEXTURES_TABLE] = {
  "figures/tabl_base.ppm",
  "figures/tabl_ocean.ppm",
  "figures/tabl_found.ppm",
  "figures/tabl_missed.ppm",
  "figures/tabl_selected.ppm",
};


/* Raft textures' enumeration */
enum texturesRaft {
  TR_FLAG      = 0,
  TR_ROCK      = 1,
  TR_STONE     = 2,
  TR_WOODRINGS = 3,
  TR_WOOD      = 4,
};

/* Raft textures' files */
char * vpcTexturesNamesRaft[N_TEXTURES_RAFT] = {
  "figures/raft_flag.ppm",
  "figures/raft_rock.ppm",
  "figures/raft_stone.ppm",
  "figures/raft_woodrings.ppm",
  "figures/raft_wood.ppm",
};


/* Boat textures' enumeration */
enum texturesBoat {
  TB_BASE    = 0,
  TB_CABIN   = 1,
  TB_FLOOR   = 2,
  TB_GLASS   = 3,
  TB_GUNBASE = 4,
  TB_GUN     = 5,
};

/* Boat textures' files */
char * vpcTexturesNamesBoat[N_TEXTURES_BOAT] = {
  "figures/boat_base.ppm",
  "figures/boat_cabin.ppm",
  "figures/boat_floor.ppm",
  "figures/boat_glass.ppm",
  "figures/boat_gunbase.ppm",
  "figures/boat_gun.ppm",
};


/* Submarine textures' enumeration */
enum texturesSubmarine {
  TS_BODY      = 0,
  TS_ENTRY1    = 1,
  TS_ENTRY2    = 2,
  TS_GUNFRONT  = 3,
  TS_GUNLATER  = 4,
  TS_OTHERS    = 5,
  TS_WINDOW    = 6,
};

/* Submarine textures' files */
char * vpcTexturesNamesSubmarine[N_TEXTURES_SUBMARINE] = {
  "figures/subm_body.ppm",
  "figures/subm_entry1.ppm",
  "figures/subm_entry2.ppm",
  "figures/subm_gunfront.ppm",
  "figures/subm_gunlater.ppm",
  "figures/subm_others.ppm",
  "figures/subm_window.ppm",
};


/* Vessel textures' enumeration */
enum texturesVessel {
  TV_BASE     = 0,
  TV_CABIN1   = 1,
  TV_CABIN2   = 2,
  TV_CHIMNEY  = 3,
  TV_FLOOR    = 4,
  TV_GLASS    = 5,
  TV_GUNBASE  = 6,
  TV_GUN      = 7,
  TV_LIFEBOAT = 8,
};

/* Vessel textures' files */
char * vpcTexturesNamesVessel[N_TEXTURES_VESSEL] = {
  "figures/vess_base.ppm",
  "figures/vess_cabin1.ppm",
  "figures/vess_cabin2.ppm",
  "figures/vess_chimney.ppm",
  "figures/vess_floor.ppm",
  "figures/vess_glass.ppm",
  "figures/vess_gunbase.ppm",
  "figures/vess_gun.ppm",
  "figures/vess_lifeboat.ppm",
};


/* Sun textures' enumeration */
enum texturesSun {
  TN_INNER  = 0,
  TN_OUTTER = 1,
};

/* Sun textures' files */
char * vpcTexturesNamesSun[N_TEXTURES_SUN] = {
  "figures/sun__inner.ppm",
  "figures/sun__outter.ppm",
};


/* Moon textures' enumeration */
enum texturesMoon {
  TM_SURFACE = 0,
};

/* Moon textures' files */
char * vpcTexturesNamesMoon[N_TEXTURES_MOON] = {
  "figures/moon_surface.ppm",
};



/**
 * Internal functions for loading models' textures
 */
void generateTexturesTable(void);
void generateTexturesRaft(void);
void generateTexturesBoat(void);
void generateTexturesSubmarine(void);
void generateTexturesVessel(void);
void generateTexturesSun(void);
void generateTexturesMoon(void);


/**
 * Vectors for textures identifiers
 */
GLuint vuiTexturesTable    [N_TEXTURES_TABLE];
GLuint vuiTexturesRaft     [N_TEXTURES_RAFT];
GLuint vuiTexturesBoat     [N_TEXTURES_BOAT];
GLuint vuiTexturesSubmarine[N_TEXTURES_SUBMARINE];
GLuint vuiTexturesVessel   [N_TEXTURES_TABLE];
GLuint vuiTexturesSun      [N_TEXTURES_SUN];
GLuint vuiTexturesMoon     [N_TEXTURES_MOON];




/**
 * Function for creating all models
 */
void createAllModels(void)
{
  /* Tables */
  createTable();
  createAuxTable();


  /* Ships */
  createRaft();
  createBoat();
  createSubmarine();
  createVessel();


  /* Sun and moon */
  createSun();
  createMoon();


  /* Ships' emissive parts */
  createEmissivePartsRaft();
  createEmissivePartsBoat();
  createEmissivePartsSubmarine();
  createEmissivePartsVessel();
}


/**
 * Create table function
 */
void createTable(void)
{
  /* Loading textures of table */
  generateTexturesTable();


  glNewList(TABLE, GL_COMPILE);
  {
    int iLineIdx;
    int iXSquareIdx;
    int iYSquareIdx;

    /* Table material colors */
    GLfloat vfTableSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfTableEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fTableShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfTableSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfTableEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fTableShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    /* Table Base */
    glColor3f(0.8, 0.8, 0.8);
    glBindTexture(GL_TEXTURE_2D, vuiTexturesTable[TT_BASE]);
    glBegin(GL_POLYGON);
    {
      glNormal3d(0.0, 0.0, -1.0);
      glTexCoord2d(0.0, 0.0);
      glVertex3d(-TB_SIZE/2.0-2.0, -TB_SIZE/2.0-2.0, -2.0);
      glTexCoord2d(0.0, 1.0);
      glVertex3d(-TB_SIZE/2.0-2.0,  TB_SIZE/2.0+2.0, -2.0);
      glTexCoord2d(1.0, 1.0);
      glVertex3d( TB_SIZE/2.0+2.0,  TB_SIZE/2.0+2.0, -2.0);
      glTexCoord2d(1.0, 0.0);
      glVertex3d( TB_SIZE/2.0+2.0, -TB_SIZE/2.0-2.0, -2.0);
    }
    glEnd();

    glBegin(GL_POLYGON);
    {
      glNormal3d(0.0, -0.707, 0.707);
      glTexCoord2d(0.0, 0.3);
      glVertex3d(-TB_SIZE/2.0,     -TB_SIZE/2.0,      0.0);
      glTexCoord2d(0.0, 0.8);
      glVertex3d(-TB_SIZE/2.0-2.0, -TB_SIZE/2.0-2.0, -2.0);
      glTexCoord2d(1.3, 0.8);
      glVertex3d( TB_SIZE/2.0+2.0, -TB_SIZE/2.0-2.0, -2.0);
      glTexCoord2d(1.3, 0.3);
      glVertex3d( TB_SIZE/2.0,     -TB_SIZE/2.0,      0.0);
    }
    glEnd();

    glBegin(GL_POLYGON);
    {
      glNormal3d(0.707, 0.0, 0.707);
      glTexCoord2d(0.0, 0.4);
      glVertex3d(TB_SIZE/2.0,     -TB_SIZE/2.0,      0.0);
      glTexCoord2d(0.0, 0.9);
      glVertex3d(TB_SIZE/2.0+2.0, -TB_SIZE/2.0-2.0, -2.0);
      glTexCoord2d(1.3, 0.9);
      glVertex3d(TB_SIZE/2.0+2.0,  TB_SIZE/2.0+2.0, -2.0);
      glTexCoord2d(1.3, 0.4);
      glVertex3d(TB_SIZE/2.0,      TB_SIZE/2.0,      0.0);
    }
    glEnd();

    glBegin(GL_POLYGON);
    {
      glNormal3d(0.0, 0.707, 0.707);
      glTexCoord2d(0.0, 0.2);
      glVertex3d( TB_SIZE/2.0,      TB_SIZE/2.0,      0.0);
      glTexCoord2d(0.0, 0.7);
      glVertex3d( TB_SIZE/2.0+2.0,  TB_SIZE/2.0+2.0, -2.0);
      glTexCoord2d(1.3, 0.7);
      glVertex3d(-TB_SIZE/2.0-2.0,  TB_SIZE/2.0+2.0, -2.0);
      glTexCoord2d(1.3, 0.2);
      glVertex3d(-TB_SIZE/2.0,      TB_SIZE/2.0,      0.0);
    }
    glEnd();

    glBegin(GL_POLYGON);
    {
      glNormal3d(-0.707, 0.0, 0.707);
      glTexCoord2d(0.0, 0.0);
      glVertex3d(-TB_SIZE/2.0,      TB_SIZE/2.0,      0.0);
      glTexCoord2d(0.0, 0.5);
      glVertex3d(-TB_SIZE/2.0-2.0,  TB_SIZE/2.0+2.0, -2.0);
      glTexCoord2d(1.3, 0.5);
      glVertex3d(-TB_SIZE/2.0-2.0, -TB_SIZE/2.0-2.0, -2.0);
      glTexCoord2d(1.3, 0.0);
      glVertex3d(-TB_SIZE/2.0,     -TB_SIZE/2.0,      0.0);
    }
    glEnd();


    /* Table squares */
    for (iXSquareIdx = 0; iXSquareIdx < TB_NSQUARES; ++iXSquareIdx)
      for (iYSquareIdx = 0; iYSquareIdx < TB_NSQUARES; ++iYSquareIdx)
	{
	  glPushMatrix();
	  {
	    glTranslatef(TB_X0+(iXSquareIdx  )*TB_SQUARE_SIZE,
			 TB_Y0+(iYSquareIdx  )*TB_SQUARE_SIZE, 0.0);

	    if ((iXSquareIdx+iYSquareIdx)%2 == 0) /* The sum is even */
	      glColor3f(0.0, 0.0, 0.85);
	    else
	      glColor3f(0.0, 0.0, 0.50);

	    glBindTexture(GL_TEXTURE_2D, vuiTexturesTable[TT_OCEAN]);
	    glBegin(GL_POLYGON);
	    {
	      glNormal3d(0.0, 0.0, 1.0);
	      glTexCoord2d(2.5*(iXSquareIdx  )/TB_NSQUARES,
			   2.5*(iYSquareIdx  )/TB_NSQUARES);
	      glVertex2d(0.0, 0.0);
	      glTexCoord2d(2.5*(iXSquareIdx+1)/TB_NSQUARES,
			   2.5*(iYSquareIdx  )/TB_NSQUARES);
	      glVertex2d(TB_SQUARE_SIZE, 0.0);
	      glTexCoord2d(2.5*(iXSquareIdx+1)/TB_NSQUARES,
			   2.5*(iYSquareIdx+1)/TB_NSQUARES);
	      glVertex2d(TB_SQUARE_SIZE, TB_SQUARE_SIZE);
	      glTexCoord2d(2.5*(iXSquareIdx  )/TB_NSQUARES,
			   2.5*(iYSquareIdx+1)/TB_NSQUARES);
	      glVertex2d(0.0, TB_SQUARE_SIZE);
	    }
	    glEnd();
	  }
	  glPopMatrix();
	}
  }
  glEndList();


  /* Squares */
  createSquareFound();
  createSquareMissed();
  createSquareSelected();
}


/**
 * Auxiliary Table
 */
void createAuxTable(void)
{
  glNewList(AUXTABLE, GL_COMPILE);
  {
    int iXSquareIdx;
    int iYSquareIdx;


    /* Table squares */
    for (iXSquareIdx = 0; iXSquareIdx < TB_NSQUARES; ++iXSquareIdx)
      for (iYSquareIdx = 0; iYSquareIdx < TB_NSQUARES; ++iYSquareIdx)
	{
	  glColor3ub(iXSquareIdx, iYSquareIdx, (GLubyte) 255);
	  glBegin(GL_POLYGON);
	  {
	    glVertex2d(TB_X0+(iXSquareIdx  )*TB_SQUARE_SIZE,
		       TB_Yn-(iYSquareIdx  )*TB_SQUARE_SIZE);
	    glVertex2d(TB_X0+(iXSquareIdx+1)*TB_SQUARE_SIZE,
		       TB_Yn-(iYSquareIdx  )*TB_SQUARE_SIZE);
	    glVertex2d(TB_X0+(iXSquareIdx+1)*TB_SQUARE_SIZE,
		       TB_Yn-(iYSquareIdx+1)*TB_SQUARE_SIZE);
	    glVertex2d(TB_X0+(iXSquareIdx  )*TB_SQUARE_SIZE,
		       TB_Yn-(iYSquareIdx+1)*TB_SQUARE_SIZE);
	  }
	  glEnd();
	}
  }
  glEndList();
}


/**
 *
 */
void createSquareFound(void)
{
  glNewList(SQUARE_FOUND, GL_COMPILE);
  {
    /* Table material colors */
    GLfloat vfTableSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfTableEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fTableShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfTableSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfTableEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fTableShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glColor3f(1.0, 0.0, 0.0);
    glBindTexture(GL_TEXTURE_2D, vuiTexturesTable[TT_FOUND]);

    glBegin(GL_POLYGON);
    {
      glNormal3d(0.0, 0.0, 1.0);
      glTexCoord2d(0.0, 0.0); glVertex2d(           0.0,            0.0);
      glTexCoord2d(1.0, 0.0); glVertex2d(TB_SQUARE_SIZE,            0.0);
      glTexCoord2d(1.0, 1.0); glVertex2d(TB_SQUARE_SIZE, TB_SQUARE_SIZE);
      glTexCoord2d(0.0, 1.0); glVertex2d(           0.0, TB_SQUARE_SIZE);
    }
    glEnd();
  }
  glEndList();
}


/**
 *
 */
void createSquareMissed(void)
{
  glNewList(SQUARE_MISSED, GL_COMPILE);
  {
    /* Table material colors */
    GLfloat vfTableSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfTableEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fTableShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfTableSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfTableEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fTableShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glColor3f(0.2, 0.2, 0.65);
    glBindTexture(GL_TEXTURE_2D, vuiTexturesTable[TT_MISSED]);

    glBegin(GL_POLYGON);
    {
      glNormal3d(0.0, 0.0, 1.0);
      glTexCoord2d(0.0, 0.0); glVertex2d(           0.0,            0.0);
      glTexCoord2d(1.0, 0.0); glVertex2d(TB_SQUARE_SIZE,            0.0);
      glTexCoord2d(1.0, 1.0); glVertex2d(TB_SQUARE_SIZE, TB_SQUARE_SIZE);
      glTexCoord2d(0.0, 1.0); glVertex2d(           0.0, TB_SQUARE_SIZE);
    }
    glEnd();
  }
  glEndList();
}


/**
 *
 */
void createSquareSelected(void)
{
  glNewList(SQUARE_SELECTED, GL_COMPILE);
  {
    /* Table material colors */
    GLfloat vfTableSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfTableEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fTableShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfTableSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfTableEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fTableShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glBindTexture(GL_TEXTURE_2D, vuiTexturesTable[TT_SELECTED]);

    glBegin(GL_POLYGON);
    {
      glNormal3d(0.0, 0.0, 1.0);
      glTexCoord2d(0.0, 0.0); glVertex2d(           0.0,            0.0);
      glTexCoord2d(1.0, 0.0); glVertex2d(TB_SQUARE_SIZE,            0.0);
      glTexCoord2d(1.0, 1.0); glVertex2d(TB_SQUARE_SIZE, TB_SQUARE_SIZE);
      glTexCoord2d(0.0, 1.0); glVertex2d(           0.0, TB_SQUARE_SIZE);
    }
    glEnd();
  }
  glEndList();
}


/**
 * RAFT
 */
void createRaft(void)
{
  /* Loading textures of raft */
  generateTexturesRaft();


  glNewList(RAFT, GL_COMPILE);
  {
    /* Control points for Bezier surface */
    GLdouble m3dControlPoints[4][4][3] = {
      { { -2.5, 10.0, 1.5 },
	{ -2.0, 11.5, 3.0 },
	{ -1.5, 10.3, 4.7 },
	{ -1.2, 10.0, 6.5 } },

      {	{ -1.0, 10.7, 1.5 },
	{ -0.7, 11.9, 3.0 },
	{ -0.5, 11.0, 4.7 },
	{ -0.7, 10.5, 6.5 } },

      {	{  1.0, 10.7, 1.5 },
	{  0.7, 11.9, 3.0 },
	{  0.5, 11.0, 4.7 },
	{  0.7, 10.5, 6.5 } },

      {	{  2.5, 10.0, 1.5 },
	{  2.0, 11.5, 3.0 },
	{  1.5, 10.3, 4.7 },
	{  1.2, 10.0, 6.5 } }
    };

    int iCylinder;

    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();
    gluQuadricTexture(quadric, GL_TRUE);

    /* Raft material colors */
    GLfloat vfRaftSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfRaftEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fRaftShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfRaftSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfRaftEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fRaftShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glPushMatrix();
    {
      /* Normalizing width 12 to 1 */
      glScaled(1.0/12.0, 1.0/12.0, 1.0/12.0);
      glTranslated(0.0, 0.0, -0.2);


      /** The base **/
      glColor3f(0.7, 0.4, 0.2);
      for (iCylinder = 0; iCylinder < 6; ++iCylinder)
	{
	  /* Drawing trunk */
	  glPushMatrix();
	  {
	    glTranslated(-2.5+iCylinder, 2.5, 0.5);
	    glRotated(90.0, 1.0, 0.0, 0.0);
	    glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOODRINGS]);
	    gluDisk(quadric, 0.0, 0.5, 16, 6);

	    glRotated(180.0, 1.0, 0.0, 0.0);
	    glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOOD]);
	    gluCylinder(quadric, 0.5, 0.5, 9.0, 16, 8);

	    glTranslated(0.0, 0.0, 9.0);
	    glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOODRINGS]);
	    gluDisk(quadric, 0.0, 0.5, 16, 6);
	  }
	  glPopMatrix();
	}


      /** The catapult **/
      /* Drawing base */
      glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOOD]);
      glPushMatrix();
      {
	glTranslated(-0.5, 4.0, 1.7071);
	glRotated(45.0, 1.0, 0.0, 0.0);
	glScaled(1.0, 10.0, 2.0);
	glutSolidCube(0.25);

	glTranslated(1.0, 0.0, 0.0);
	glutSolidCube(0.25);
      }
      glPopMatrix();

      glPushMatrix();
      {
	glTranslated(-0.25, 5.4142, 1.7071);
	glRotated(-45.0, 1.0, 0.0, 0.0);
	glScaled(1.0, 10.0, 2.0);
	glutSolidCube(0.25);

	glTranslated(0.5, 0.0, 0.0);
	glutSolidCube(0.25);
      }
      glPopMatrix();

      /* Drawing rotation axis */
      glColor3f(0.3, 0.3, 0.3);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_STONE]);
      glPushMatrix();
      {
	glTranslated(-0.8, 4.7071, 2.4142);
	glRotated(-90.0, 0.0, 1.0, 0.0);
	gluDisk(quadric, 0.0, 0.15, 16, 6);

 	glRotated(180.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.15, 0.15, 1.6, 8, 8);

	glTranslated(0.0, 0.0, 1.6);
	gluDisk(quadric, 0.0, 0.15, 16, 6);
      }
      glPopMatrix();

      glPushMatrix();
      {
	/* Drawing ball recepient planes */
	glTranslated(0.0, 4.7071, 2.4142);
 	glRotated(-20.0, 1.0, 0.0, 0.0);

	glBegin(GL_POLYGON);
	{
	  glNormal3d(0.0, 0.0, -1.0);
	  glTexCoord2d(0.0, 0.0); glVertex3d(-0.5, 2.0, -0.25);
	  glTexCoord2d(0.0, 1.0); glVertex3d(-0.5, 3.0, -0.25);
	  glTexCoord2d(1.0, 1.0); glVertex3d( 0.5, 3.0, -0.25);
	  glTexCoord2d(1.0, 0.0); glVertex3d( 0.5, 2.0, -0.25);
	}
	glEnd();

	glBegin(GL_POLYGON);
	{
	  glNormal3d(0.0, -0.8321, -0.5547);
	  glTexCoord2d(0.0, 0.0); glVertex3d(-0.5, 2.0, -0.25);
	  glTexCoord2d(0.0, 1.0); glVertex3d( 0.5, 2.0, -0.25);
	  glTexCoord2d(1.0, 1.0); glVertex3d( 1.0, 1.5,  0.50);
	  glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, 1.5,  0.50);
	}
	glEnd();

	glBegin(GL_POLYGON);
	{
	  glNormal3d(-0.8321, 0.0, -0.5547);
	  glTexCoord2d(0.0, 0.0); glVertex3d(-0.5, 3.0, -0.25);
	  glTexCoord2d(0.0, 1.0); glVertex3d(-0.5, 2.0, -0.25);
	  glTexCoord2d(1.0, 1.0); glVertex3d(-1.0, 1.5,  0.50);
	  glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, 3.5,  0.50);
	}
	glEnd();

	glBegin(GL_POLYGON);
	{
	  glNormal3d(0.0, 0.8321, -0.5547);
	  glTexCoord2d(0.0, 0.0); glVertex3d( 0.5, 3.0, -0.25);
	  glTexCoord2d(0.0, 1.0); glVertex3d(-0.5, 3.0, -0.25);
	  glTexCoord2d(1.0, 1.0); glVertex3d(-1.0, 3.5,  0.50);
	  glTexCoord2d(1.0, 0.0); glVertex3d( 1.0, 3.5,  0.50);
	}
	glEnd();

	glBegin(GL_POLYGON);
	{
	  glNormal3d(0.8321, 0.0, -0.5547);
	  glTexCoord2d(0.0, 0.0); glVertex3d( 0.5, 2.0, -0.25);
	  glTexCoord2d(0.0, 1.0); glVertex3d( 0.5, 3.0, -0.25);
	  glTexCoord2d(1.0, 1.0); glVertex3d( 1.0, 3.5,  0.50);
	  glTexCoord2d(1.0, 0.0); glVertex3d( 1.0, 1.5,  0.50);
	}
	glEnd();

	glBegin(GL_POLYGON);
	{
	  glNormal3d(0.0, 0.0, 1.0);
	  glTexCoord2d(0.0, 0.0); glVertex3d(-1.0, 1.5,  0.50);
	  glTexCoord2d(0.0, 1.0); glVertex3d( 1.0, 1.5,  0.50);
	  glTexCoord2d(1.0, 1.0); glVertex3d( 1.0, 3.5,  0.50);
	  glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, 3.5,  0.50);
	}
	glEnd();

	/* Drawing cubic rock */
	glTranslated(0.0, -3.5, 0.0);
	glutSolidCube(1.5);

	/* Drawing ball */
	glColor3f(0.7, 0.5, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_ROCK]);
	glTranslated(0.0, 6.0, 0.5);
	gluSphere(quadric, 0.75, 16, 8);

	/* Drawing ball-rock linking wood */
	glColor3f(0.7, 0.4, 0.2);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOOD]);
	glTranslated(0.0, -3.0, -0.5);
	glScaled(0.25, 5.0, 0.5);
	glutSolidCube(1.0);
      }
      glPopMatrix();


      /** The mast **/
      /* Drawing vertical part */
      glPushMatrix();
      {
	glTranslated(0.0, 9.75, 0.5);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOOD]);
	gluCylinder(quadric, 0.25, 0.25, 6.5, 8, 8);

	glTranslated(0.0, 0.0, 6.5);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOODRINGS]);
	gluDisk(quadric, 0.0, 0.25, 8, 6);
      }
      glPopMatrix();

      /* Drawing horizontal part */
      glPushMatrix();
      {
	glTranslated(-2.0, 9.75, 5.5);
 	glRotated(-90, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOODRINGS]);
	gluDisk(quadric, 0, 0.25, 8, 6);

	glRotated(180.0, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOOD]);
	gluCylinder(quadric, 0.25, 0.25, 4.0, 8, 8);

	glTranslated(0.0, 0.0, 4.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_WOODRINGS]);
	gluDisk(quadric, 0.0, 0.25, 8, 6);
      }
      glPopMatrix();


      /** The lamp **/
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_BLEND);
      glColor4f(0.9, 0.9, 1.0, 0.5);
      glPushMatrix();
      {
	glTranslated(0.0, 9.75, 7.25);
	gluSphere(quadric, 0.25, 8, 8);
      }
      glPopMatrix();
      glDisable(GL_BLEND);
      

      /** The sail **/
      /* Configuring Bezier surface parameters and drawing sail */
      glColor3f(1.0, 1.0, 1.0);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[TR_FLAG]);
      glEnable(GL_MAP2_VERTEX_3);
      glMap2d(GL_MAP2_VERTEX_3,
	      0.0, 1.0,  3, 4,
	      0.0, 1.0, 12, 4, &m3dControlPoints[0][0][0]);
      glMapGrid2d(30, 0.0, 1.0, 30, 0.0, 1.0);

      /* Drawing sail */
      glEvalMesh2(GL_FILL, 0, 30.0, 0.0, 30.0);
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * RAFT EMISSIVE PARTS
 */
void createEmissivePartsRaft(void)
{
  glNewList(EMISSIVE_PARTS_RAFT, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();

    /* Raft emissive material colors */
    GLfloat vfRaftSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfRaftEmission[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat  fRaftShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfRaftSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfRaftEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fRaftShininess);


    glPushMatrix();
    {
      /* Normalizing width 12 to 1 */
      glScaled(1.0/12.0, 1.0/12.0, 1.0/12.0);
      glTranslated(0.0, 0.0, -0.2);

      /* Drawing lamp of mast */
      glColor3f(1.0, 1.0, 1.0);
      glPushMatrix();
      {
	glTranslated(0.0, 9.75, 7.25);
	gluSphere(quadric, 0.27, 8, 8);
      }
      glPopMatrix();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * BOAT
 */
void createBoat(void)
{
  /* Loading textures of boat */
  generateTexturesBoat();


  glNewList(BOAT, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();
    gluQuadricTexture(quadric, GL_TRUE);

    /* Boat material colors */
    GLfloat vfBoatSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfBoatEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fBoatShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfBoatSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfBoatEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fBoatShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glPushMatrix();
    {
      /* Normalizing width 6 to 1 */
      glScaled(1.0/6.0, 1.0/6.0, 1.0/6.0);


      /** The hull **/
      /* Drawing back */
      glColor3f(0.2, 0.2, 0.7);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[TB_BASE]);
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, -0.8321, -0.5547);
	glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0,  2.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0,  2.0);
	glTexCoord2d(0.5, 0.0); glVertex3d( 0.0,  3.0, -1.0);
      }
      glEnd();

      /* Drawing left back */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.5774, -0.5774, -0.5774);
	glTexCoord2d(1.0, 1.0); glVertex3d(-1.0,  1.0,  2.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-2.0,  2.0,  2.0);
	glTexCoord2d(0.5, 1.0); glVertex3d( 0.0,  3.0, -1.0);
      }
      glEnd();

      /* Drawing right back */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.5774, -0.5774, -0.5774);
	glTexCoord2d(1.0, 1.0); glVertex3d( 2.0,  2.0,  2.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 1.0,  1.0,  2.0);
	glTexCoord2d(0.5, 1.0); glVertex3d( 0.0,  3.0, -1.0);
      }
      glEnd();

      /* Drawing left lateral */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.8321, 0.0, -0.5747);
	glTexCoord2d(0.0, 1.0); glVertex3d(-2.0,  2.0,  2.0);
	glTexCoord2d(2.0, 1.0); glVertex3d(-2.0,  7.0,  2.0);
	glTexCoord2d(2.0, 0.0); glVertex3d( 0.0,  9.0, -1.0);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.0,  3.0, -1.0);
      }
      glEnd();

      /* Drawing right lateral */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.8321, 0.0, -0.5747);
	glTexCoord2d(2.0, 1.0); glVertex3d( 2.0,  7.0,  2.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 2.0,  2.0,  2.0);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.0,  3.0, -1.0);
	glTexCoord2d(2.0, 0.0); glVertex3d( 0.0,  9.0, -1.0);
      }
      glEnd();

      /* Drawing left front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.8723, 0.3271, -0.3635);
	glTexCoord2d(0.0, 2.0); glVertex3d(-0.5, 11.0,  2.0);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.0,  9.0, -1.0);
	glTexCoord2d(2.0, 2.0); glVertex3d(-2.0,  7.0,  2.0);
      }
      glEnd();

      /* Drawing right front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.8723, 0.3271, -0.3635);
	glTexCoord2d(0.0, 2.0); glVertex3d( 0.5, 11.0,  2.0);
	glTexCoord2d(1.0, 0.0); glVertex3d( 2.0,  7.0,  2.0);
	glTexCoord2d(2.0, 2.0); glVertex3d( 0.0,  9.0, -1.0);
      }
      glEnd();

      /* Drawing front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.8321, -0.5547);
	glTexCoord2d(0.0, 2.0); glVertex3d(-0.5, 11.0,  2.0);
	glTexCoord2d(1.0, 2.0); glVertex3d( 0.5, 11.0,  2.0);
	glTexCoord2d(0.5, 0.0); glVertex3d( 0.0,  9.0, -1.0);
      }
      glEnd();

      /* Drawing floor */
      glColor3f(0.6, 0.5, 0.1); 
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[TB_FLOOR]);
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glTexCoord2d(0.0,  0.250); glVertex3d( 1.0,  1.0,  2.0);
	glTexCoord2d(0.2,  0.500); glVertex3d( 2.0,  2.0,  2.0);
	glTexCoord2d(1.2,  0.500); glVertex3d( 2.0,  7.0,  2.0);
	glTexCoord2d(2.0,  0.125); glVertex3d( 0.5, 11.0,  2.0);
	glTexCoord2d(2.0, -0.125); glVertex3d(-0.5, 11.0,  2.0);
	glTexCoord2d(1.2, -0.500); glVertex3d(-2.0,  7.0,  2.0);
	glTexCoord2d(0.2, -0.500); glVertex3d(-2.0,  2.0,  2.0);
	glTexCoord2d(0.0, -0.250); glVertex3d(-1.0,  1.0,  2.0);
      }
      glEnd();


      /** The cabin **/
      /* Drawing back */
      glColor3f(1.0, 1.0, 1.0);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[TB_CABIN]);
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, -0.7071, 0.7071);
	glTexCoord2d(1.0, 0.0); glVertex3d( 1.0,  2.0,  2.0);
	glTexCoord2d(0.7, 1.0); glVertex3d( 0.5,  3.0,  3.0);
	glTexCoord2d(0.3, 1.0); glVertex3d(-0.5,  3.0,  3.0);
	glTexCoord2d(0.0, 0.0); glVertex3d(-1.0,  2.0,  2.0);
      }
      glEnd();

      /* Drawing left lateral */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.8944, 0.0, 0.4472);
	glTexCoord2d(0.0, 0.0); glVertex3d(-1.0,  2.0,  2.0);
	glTexCoord2d(0.4, 1.0); glVertex3d(-0.5,  3.0,  3.0);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.5,  4.5,  3.0);
	glTexCoord2d(0.8, 0.0); glVertex3d(-1.0,  4.0,  2.0);
      }
      glEnd();

      /* Drawing right lateral */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.8944, 0.0, 0.4472);
	glTexCoord2d(0.4, 1.0); glVertex3d( 0.5,  3.0,  3.0);
	glTexCoord2d(0.0, 0.0); glVertex3d( 1.0,  2.0,  2.0);
	glTexCoord2d(0.8, 0.0); glVertex3d( 1.0,  4.0,  2.0);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.5,  4.5,  3.0);
      }
      glEnd();

      /* Drawing top */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.5,  3.0,  3.0);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.5,  4.5,  3.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.5,  4.5,  3.0);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.5,  3.0,  3.0);
      }
      glEnd();

      /* Drawing left front */
      glColor3f(0.5, 0.5, 1.0);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[TB_GLASS]);
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.9117, 0.2279, 0.3419);
	glTexCoord2d(0.25, 1.0); glVertex3d(-0.5,  4.5,  3.0);
	glTexCoord2d(1.00, 0.0); glVertex3d(-0.5,  6.0,  2.0);
	glTexCoord2d(1.00, 0.0); glVertex3d(-1.0,  4.0,  2.0);
      }
      glEnd();

      /* Drawing right front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.9117, 0.2279, 0.3419);
	glTexCoord2d(1.00, 0.0); glVertex3d( 0.5,  6.0,  2.0);
	glTexCoord2d(0.25, 1.0); glVertex3d( 0.5,  4.5,  3.0);
	glTexCoord2d(0.00, 0.0); glVertex3d( 1.0,  4.0,  2.0);
      }
      glEnd();

      /* Drawing front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.5547, 0.8321, 0.0);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.5,  6.0,  2.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.5,  4.5,  3.0);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.5,  4.5,  3.0);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.5,  6.0,  2.0);
      }
      glEnd();


      /** The lamp **/
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_BLEND);
      glColor4f(0.9, 0.9, 1.0, 0.5);
      glPushMatrix();
      {
	glTranslated(0.0, 4.2, 3.05);
	gluSphere(quadric, 0.125, 8, 8);
      }
      glPopMatrix();
      glDisable(GL_BLEND);
      

      /** The gun **/
      /* Drawing base */
      glColor3f(0.5, 0.5, 0.5);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[TB_GUNBASE]);
      glPushMatrix();
      {
	glTranslated(0.0, 8.0, 2.0);
	gluCylinder(quadric, 1.0, 1.0, 0.5, 32, 8);

	glTranslated(0.0, 0.0, 0.5);
	gluDisk(quadric, 0.0, 1.0, 32, 8);
      }
      glPopMatrix();


      /* Support */
      glColor3f(1.0, 1.0, 1.0);
      glPushMatrix();
      {
	glTranslated(0.0, 8.0, 2.5);
	glScaled(1.0, 1.0, 0.5);
	glutSolidCube(1.0);
      }
      glPopMatrix();

      /* Drawing gun itself */
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[TB_GUN]);
      glPushMatrix();
      {
	glTranslated(-0.25, 7.75, 2.5);
	glRotated(-70.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.20, 0.20, 2.5, 8, 8);

	glTranslated(0.5, 0.0, 0.0);
	gluCylinder(quadric, 0.20, 0.20, 2.5, 8, 8);
      }
      glPopMatrix();


      /** The protection lines **/
      /* First Line */
      glColor3f(1.0, 1.0, 1.0);
      glBegin(GL_LINE_LOOP);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glVertex3d( 1.0,  1.0,  2.25);
	glVertex3d( 2.0,  2.0,  2.25);
	glVertex3d( 2.0,  7.0,  2.25);
	glVertex3d( 0.5, 11.0,  2.25);
	glVertex3d(-0.5, 11.0,  2.25);
	glVertex3d(-2.0,  7.0,  2.25);
	glVertex3d(-2.0,  2.0,  2.25);
	glVertex3d(-1.0,  1.0,  2.25);
      }
      glEnd();

      /* Second Line */
      glBegin(GL_LINE_LOOP);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glVertex3d( 1.0,  1.0,  2.5);
	glVertex3d( 2.0,  2.0,  2.5);
	glVertex3d( 2.0,  7.0,  2.5);
	glVertex3d( 0.5, 11.0,  2.5);
	glVertex3d(-0.5, 11.0,  2.5);
	glVertex3d(-2.0,  7.0,  2.5);
	glVertex3d(-2.0,  2.0,  2.5);
	glVertex3d(-1.0,  1.0,  2.5);
      }
      glEnd();

      /* Vertical lines */
      glColor3f(0.1, 0.1, 0.1);
      glBegin(GL_LINES);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glVertex3d( 1.0,  1.0,  2.0);
	glVertex3d( 1.0,  1.0,  2.5);
	glVertex3d( 2.0,  2.0,  2.0);
	glVertex3d( 2.0,  2.0,  2.5);
	glVertex3d( 2.0,  7.0,  2.0);
	glVertex3d( 2.0,  7.0,  2.5);
	glVertex3d( 0.5, 11.0,  2.0);
	glVertex3d( 0.5, 11.0,  2.5);
	glVertex3d(-0.5, 11.0,  2.0);
	glVertex3d(-0.5, 11.0,  2.5);
	glVertex3d(-2.0,  7.0,  2.0);
	glVertex3d(-2.0,  7.0,  2.5);
	glVertex3d(-2.0,  2.0,  2.0);
	glVertex3d(-2.0,  2.0,  2.5);
	glVertex3d(-1.0,  1.0,  2.0);
	glVertex3d(-1.0,  1.0,  2.5);
      }
      glEnd();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * BOAT EMISSIVE PARTS
 */
void createEmissivePartsBoat(void)
{
  glNewList(EMISSIVE_PARTS_BOAT, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();
    gluQuadricTexture(quadric, GL_TRUE);

    /* Boat material colors */
    GLfloat vfBoatSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfBoatEmission[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat  fBoatShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfBoatSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfBoatEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fBoatShininess);


    glPushMatrix();
    {
      /* Normalizing width 6 to 1 */
      glScaled(1.0/6.0, 1.0/6.0, 1.0/6.0);


      /** The cabin **/
      /* Drawing left front */
      glColor3f(0.5, 0.5, 1.0);
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.9117, 0.2279, 0.3419);
	glVertex3d(-0.5,  4.5,  3.0);
	glVertex3d(-0.5,  6.0,  2.0);
	glVertex3d(-1.0,  4.0,  2.0);
      }
      glEnd();

      /* Drawing right front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.9117, 0.2279, 0.3419);
	glVertex3d( 0.5,  6.0,  2.0);
	glVertex3d( 0.5,  4.5,  3.0);
	glVertex3d( 1.0,  4.0,  2.0);
      }
      glEnd();

      /* Drawing front */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.5547, 0.8321, 0.0);
	glVertex3d(-0.5,  6.0,  2.0);
	glVertex3d(-0.5,  4.5,  3.0);
	glVertex3d( 0.5,  4.5,  3.0);
	glVertex3d( 0.5,  6.0,  2.0);
      }
      glEnd();


      /** The lamp **/
      glColor3f(0.9, 0.9, 1.0);
      glPushMatrix();
      {
	glTranslated(0.0, 4.2, 3.05);
	gluSphere(quadric, 0.125, 8, 8);
      }
      glPopMatrix();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * SUBMARINE
 */
void createSubmarine(void)
{
  /* Loading textures of submarine */
  generateTexturesSubmarine();


  glNewList(SUBMARINE, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();
    gluQuadricTexture(quadric, GL_TRUE);

    /* Submarine material colors */
    GLfloat vfSubmarineSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfSubmarineEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fSubmarineShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfSubmarineSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfSubmarineEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fSubmarineShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glPushMatrix();
    {
      /* Normalizing width 4 to 1 */
      glScaled(1.0/4.0, 1.0/4.0, 1.0/4.0);
      glTranslated(0.0, 0.0, -0.5);


      /** The front **/
      glColor3f(0.0, 0.2, 0.5);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_BODY]);
      glPushMatrix();
      {
	glTranslated(0.0, 9.5, 1.2);
	glRotated(-90, 1.0, 0.0, 0.0);
	glScaled(1.2, 1.2, 2.0);
	gluSphere(quadric, 1.0, 16, 16);
      }
      glPopMatrix();


      /** The body **/
      glPushMatrix();
      {
	glTranslated(0.0, 3.5, 1.2);
	glRotated(-90, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 1.2, 1.2, 6.0, 16, 16);
      }
      glPopMatrix();


      /** The tail **/
      glPushMatrix();
      {
	glTranslated(0.0, 3.5, 1.2);
	glRotated(-90.0, 1.0, 0.0, 0.0);
	glScaled(1.2, 1.2, 1.6);
	gluSphere(quadric, 1.0, 16, 16);
      }
      glPopMatrix();

      glPushMatrix();
      {
	glTranslated(0.0, 0.5, 1.2);
	glRotated(-90.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.3, 1.15, 2.5, 16, 16);
      }
      glPopMatrix();

      glColor3f(0.5, 0.0, 0.0);
      glPushMatrix();
      {
	glTranslated(0.0, 1.0, 1.2);
	glScaled(1.6, 0.35, 0.1);
	glutSolidCube(1.0);
      }
      glPopMatrix();

      glPushMatrix();
      {
	glTranslated(0.0, 1.0, 1.2);
	glScaled(0.1, 0.35, 1.6);
	glutSolidCube(1.0);
      }
      glPopMatrix();


      /** The windows **/
      /* Drawing first window */
      glPushMatrix();
      {
	glColor3f(0.5, 0.5, 0.7);
	glTranslated(-1.25, 6.0, 1.25);
 	glRotated(-90, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
	gluDisk(quadric, 0, 0.2, 16, 6);

	glColor3f(0.0, 0.2, 0.4);
	glRotated(180.0, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_BODY]);
	gluCylinder(quadric, 0.2, 0.2, 2.5, 16, 8);

	glColor3f(0.5, 0.5, 0.7);
	glTranslated(0.0, 0.0, 2.5);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
	gluDisk(quadric, 0.0, 0.2, 16, 6);
      }
      glPopMatrix();

      /* Drawing second window */
      glPushMatrix();
      {
	glColor3f(0.5, 0.5, 0.7);
	glTranslated(-1.25, 6.5, 1.25);
 	glRotated(-90, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
	gluDisk(quadric, 0, 0.2, 16, 6);

	glColor3f(0.0, 0.2, 0.4);
	glRotated(180.0, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_BODY]);
	gluCylinder(quadric, 0.2, 0.2, 2.5, 16, 8);

	glColor3f(0.5, 0.5, 0.7);
	glTranslated(0.0, 0.0, 2.5);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
	gluDisk(quadric, 0.0, 0.2, 16, 6);
      }
      glPopMatrix();

      /* Drawing third window */
      glPushMatrix();
      {
	glColor3f(0.5, 0.5, 0.7);
	glTranslated(-1.25, 7.0, 1.25);
 	glRotated(-90, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
	gluDisk(quadric, 0, 0.2, 16, 6);

	glColor3f(0.0, 0.2, 0.4);
	glRotated(180.0, 0.0, 1.0, 0.0);
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_BODY]);
	gluCylinder(quadric, 0.2, 0.2, 2.5, 16, 8);

	glColor3f(0.5, 0.5, 0.7);
	glTranslated(0.0, 0.0, 2.5);	
	glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
	gluDisk(quadric, 0.0, 0.2, 16, 6);
      }
      glPopMatrix();


      /** The cover **/
      glColor3f(0.5, 0.0, 0.0);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_WINDOW]);
      glPushMatrix();
      {
	glTranslated(0.0, 6.5, 2.3);
	glScaled(0.5, 2.5, 1.0);
	gluCylinder(quadric, 1.0, 1.0, 0.2, 32, 32);

	glTranslated(0.0, 0.0, 0.2);
	gluDisk(quadric, 0.0, 1.0, 32, 16);
      }
      glPopMatrix();


      /** The entry **/
      glColor3f(0.5, 0.5, 0.5);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_ENTRY1]);
      glPushMatrix();
      {
	glTranslated(0.0, 6.5, 2.5);
	gluCylinder(quadric, 0.2, 0.2, 0.05, 32, 16);

	glTranslated(0.0, 0.0, 0.05);
	gluDisk(quadric, 0.0, 0.2, 32, 16);
      }
      glPopMatrix();


      /** The periscope **/
      glColor3f(0.0, 0.2, 0.4);
      glPushMatrix();
      {
	glTranslated(0.0, 8.6, 2.5);
	glScaled(0.2, 0.4, 1.0);
	gluCylinder(quadric, 1.0, 1.0, 0.4, 16, 8);

	glTranslated(0.0, 0.0, 0.4);
	gluDisk(quadric, 0.0, 1.0, 16, 8);
      }
      glPopMatrix();

      glColor3f(0.5, 0.0, 0.0);
      glPushMatrix();
      {
	glTranslated(0.0, 8.8, 2.80);
	glScaled(0.9, 0.25, 0.05);
	glutSolidCube(1.0);
      }
      glPopMatrix();


      /** The lamp **/
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_BLEND);
      glColor4f(0.9, 0.9, 1.0, 0.5);
      glPushMatrix();
      {
	glTranslated(0.0, 8.8, 2.93);
	gluSphere(quadric, 0.1, 8, 8);
      }
      glPopMatrix();
      glDisable(GL_BLEND);
      

      /** The lateral guns **/
      /* Drawing supports */
      glColor3f(0.0, 0.2, 0.4);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_BODY]);
      glPushMatrix();
      {
	glTranslated(1.3, 8.5, 1.2);
	glutSolidCube(0.4);

	glTranslated(-2.6, 0.0, 0.0);
	glutSolidCube(0.4);
      }
      glPopMatrix();

      /* Drawing guns */
      glColor3f(0.5, 0.0, 0.0);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_GUNLATER]);
      glPushMatrix();
      {
	glTranslated(1.35, 8.5, 1.2);
	glRotated(-90.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.1, 0.1, 1.2, 8, 16);

	glTranslated(-2.7, 0.0, 0.0);
	gluCylinder(quadric, 0.1, 0.1, 1.2, 8, 16);
      }
      glPopMatrix();


      /** The frontal guns **/
      glColor3f(0.5, 0.5, 0.5);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[TS_GUNFRONT]);
      glPushMatrix();
      {
	glTranslated(0.7, 10.5, 0.8);
	glRotated(-90.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.15, 0.15, 0.7, 16, 8);

	glTranslated(-1.4, 0.0, 0.0);
	gluCylinder(quadric, 0.15, 0.15, 0.7, 16, 8);
      }
      glPopMatrix();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
 }
  glEndList();
}


/**
 * SUBMARINE EMISSIVE PARTS
 */
void createEmissivePartsSubmarine(void)
{
  glNewList(EMISSIVE_PARTS_SUBMARINE, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();

    /* Submarine material colors */
    GLfloat vfSubmarineSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfSubmarineEmission[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat  fSubmarineShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfSubmarineSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfSubmarineEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fSubmarineShininess);


    glPushMatrix();
    {
      /* Normalizing width 4 to 1 */
      glScaled(1.0/4.0, 1.0/4.0, 1.0/4.0);
      glTranslated(0.0, 0.0, -0.5);


      /** The windows **/
      /* Drawing first window */
      glPushMatrix();
      {
	glColor3f(0.5, 0.5, 0.7);
	glTranslated(-1.25, 6.0, 1.25);
 	glRotated(-90, 0.0, 1.0, 0.0);
	gluDisk(quadric, 0, 0.2, 16, 6);

	glRotated(180.0, 0.0, 1.0, 0.0);
	glTranslated(0.0, 0.0, 2.5);
	gluDisk(quadric, 0.0, 0.2, 16, 6);
      }
      glPopMatrix();

      /* Drawing second window */
      glPushMatrix();
      {
	glColor3f(0.5, 0.5, 0.7);
	glTranslated(-1.25, 6.5, 1.25);
 	glRotated(-90, 0.0, 1.0, 0.0);
	gluDisk(quadric, 0, 0.2, 16, 6);

	glRotated(180.0, 0.0, 1.0, 0.0);
	glTranslated(0.0, 0.0, 2.5);
	gluDisk(quadric, 0.0, 0.2, 16, 6);
      }
      glPopMatrix();

      /* Drawing third window */
      glPushMatrix();
      {
	glColor3f(0.5, 0.5, 0.7);
	glTranslated(-1.25, 7.0, 1.25);
 	glRotated(-90, 0.0, 1.0, 0.0);
	gluDisk(quadric, 0, 0.2, 16, 6);

	glRotated(180.0, 0.0, 1.0, 0.0);
	glTranslated(0.0, 0.0, 2.5);
	gluDisk(quadric, 0.0, 0.2, 16, 6);
      }
      glPopMatrix();


      /** The lamp **/
      glColor3f(0.9, 0.9, 1.0);
      glPushMatrix();
      {
	glTranslated(0.0, 8.8, 2.93);
	gluSphere(quadric, 0.1, 8, 8);
      }
      glPopMatrix();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * VESSEL
 */
void createVessel(void)
{
  /* Loading textures of vessel */
  generateTexturesVessel();


  glNewList(VESSEL, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();
    gluQuadricTexture(quadric, GL_TRUE);

    /* Vessel material colors */
    GLfloat vfVesselSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfVesselEmission[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat  fVesselShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfVesselSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfVesselEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fVesselShininess);

    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);


    glPushMatrix();
    {
      /* Translating */
      glTranslated(0.0, 0.0, -0.15);


      /** The floor **/
      glColor3f(0.2, 0.3, 0.5);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_FLOOR]);
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glTexCoord2d(1.6, 0.0); glVertex3d(-0.35, 3.2, 0.6);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.35, 0.1, 0.6);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.35, 0.1, 0.6);
	glTexCoord2d(1.6, 1.0); glVertex3d( 0.35, 3.2, 0.6);
	glTexCoord2d(2.0, 0.5); glVertex3d( 0.00, 3.9, 0.6);
      }
      glEnd();


      /** The protection lines **/
      /* First Line */
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_LIFEBOAT]);
      glColor3f(0.5, 0.5, 0.5);
      glBegin(GL_LINE_LOOP);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glVertex3d(-0.35, 3.2, 0.625);
	glVertex3d(-0.35, 0.1, 0.625);
	glVertex3d( 0.35, 0.1, 0.625);
	glVertex3d( 0.35, 3.2, 0.625);
	glVertex3d( 0.00, 3.9, 0.625);
      }
      glEnd();

      /* Second Line */
      glBegin(GL_LINE_LOOP);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glVertex3d(-0.35, 3.2, 0.65);
	glVertex3d(-0.35, 0.1, 0.65);
	glVertex3d( 0.35, 0.1, 0.65);
	glVertex3d( 0.35, 3.2, 0.65);
	glVertex3d( 0.00, 3.9, 0.65);
      }
      glEnd();

      /* Vertical lines */
      glColor3f(0.1, 0.1, 0.1);
      glBegin(GL_LINES);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glVertex3d(-0.35, 3.2, 0.6);
	glVertex3d(-0.35, 3.2, 0.65);
	glVertex3d(-0.35, 2.1, 0.6);
	glVertex3d(-0.35, 1.1, 0.65);
	glVertex3d(-0.35, 1.1, 0.6);
	glVertex3d(-0.35, 1.1, 0.65);
	glVertex3d(-0.35, 0.1, 0.6);
	glVertex3d(-0.35, 0.1, 0.65);
	glVertex3d( 0.35, 0.1, 0.6);
	glVertex3d( 0.35, 0.1, 0.65);
	glVertex3d( 0.35, 1.1, 0.6);
	glVertex3d( 0.35, 1.1, 0.65);
	glVertex3d( 0.35, 2.1, 0.6);
	glVertex3d( 0.35, 2.1, 0.65);
	glVertex3d( 0.35, 3.2, 0.6);
	glVertex3d( 0.35, 3.2, 0.65);
	glVertex3d( 0.00, 3.9, 0.6);
	glVertex3d( 0.00, 3.9, 0.65);
      }
      glEnd();


      /** The life boat **/
      glColor3f(0.7, 0.5, 0.0);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_LIFEBOAT]);
      glPushMatrix();
      {
	glTranslated(0.3605, 2.5, 0.35);
	glRotated(104.04, 0.0, 1.0, 0.0);
	glutSolidTorus(0.05, 0.17, 24, 24);

	glTranslatef(0.0, 0.0, -0.045);
	gluDisk(quadric, 0.0, 0.16, 24, 24);
      }
      glPopMatrix();


      /** The hull **/
      glColor3f(0.2, 0.2, 0.5);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_BASE]); 

      /* Drawing bottom part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.0, -1.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.2, 3.0, 0.0);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.2, 0.3, 0.0);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.2, 0.3, 0.0);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.2, 3.0, 0.0);
      }
      glEnd();

      /* Drawing right part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.9701, 0.0, -0.2425);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.35, 0.1, 0.6);
	glTexCoord2d(0.0, 0.1); glVertex3d( 0.20, 0.3, 0.0);
	glTexCoord2d(0.0, 0.9); glVertex3d( 0.20, 3.0, 0.0);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.35, 3.2, 0.6);
      }
      glEnd();

      /* Drawing left part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.9701, 0.0, -0.2425);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.35, 3.2, 0.6);
	glTexCoord2d(0.0, 0.9); glVertex3d(-0.20, 3.0, 0.0);
	glTexCoord2d(0.0, 0.1); glVertex3d(-0.20, 0.3, 0.0);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.35, 0.1, 0.6);
      }
      glEnd();

      /* Drawing back part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, -0.9487, 0.3162);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.35, 0.1, 0.6);
	glTexCoord2d(0.1, 0.0); glVertex3d(-0.20, 0.3, 0.0);
	glTexCoord2d(0.9, 0.0); glVertex3d( 0.20, 0.3, 0.0);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.35, 0.1, 0.6);
      }
      glEnd();

      /* Drawing right frontal part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.8381, 0.4191, -0.3492);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.35, 3.2, 0.6);
	glTexCoord2d(0.0, 0.1); glVertex3d( 0.20, 3.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.00, 3.9, 0.6);
      }
      glEnd();

      /* Drawing left frontal part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-0.8381, 0.4191, -0.3492);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.00, 3.9, 0.6);
	glTexCoord2d(0.0, 0.1); glVertex3d(-0.20, 3.0, 0.0);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.35, 3.2, 0.6);
      }
      glEnd();

      /* Drawing frontal part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.5547, -0.8321);
	glTexCoord2d(0.5, 1.0); glVertex3d( 0.0, 3.9, 0.6);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.2, 3.0, 0.0);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.2, 3.0, 0.0);
      }
      glEnd();


      /** The cabin first block **/
      glColor3f(1.0, 1.0, 0.6);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_CABIN1]);

      /* Drawing top part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.25, 2.3, 0.8);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.25, 1.3, 0.8);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.25, 1.3, 0.8);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.25, 2.3, 0.8);
      }
      glEnd();

      /* Drawing right part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(1.0, 0.0, 0.0);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.25, 1.3, 0.8);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.25, 1.3, 0.6);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.25, 2.3, 0.6);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.25, 2.3, 0.8);
      }
      glEnd();

      /* Drawing left part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-1.0, 0.0, 0.0);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.25, 2.3, 0.8);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.25, 2.3, 0.6);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.25, 1.3, 0.6);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.25, 1.3, 0.8);
      }
      glEnd();

      /* Drawing back part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, -1.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.25, 1.3, 0.8);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.25, 1.3, 0.6);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.25, 1.3, 0.6);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.25, 1.3, 0.8);
      }
      glEnd();

      /* Drawing frontal part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 1.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.25, 2.3, 0.8);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.25, 2.3, 0.6);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.25, 2.3, 0.6);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.25, 2.3, 0.8);
      }
      glEnd();


      /** The windows **/
      /* Drawing frontal window */
      glColor3f(0.7, 0.7, 0.8);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_GLASS]);
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 1.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.24, 2.301, 0.79);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.24, 2.301, 0.69);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.24, 2.301, 0.69);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.24, 2.301, 0.79);
      }
      glEnd();

      /* Drawing right lateral window */
      glBegin(GL_POLYGON);
      {
	glNormal3d(1.0, 0.0, 0.0);
	glTexCoord2d(0.3, 1.0); glVertex3d(0.2505, 1.90, 0.79);
	glTexCoord2d(0.0, 0.0); glVertex3d(0.2505, 1.80, 0.69);
	glTexCoord2d(1.0, 0.0); glVertex3d(0.2505, 2.29, 0.69);
	glTexCoord2d(1.0, 1.0); glVertex3d(0.2505, 2.29, 0.79);
      }
      glEnd();

      /* Drawing left lateral window */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-1.0, 0.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.2505, 2.29, 0.79);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.2505, 2.29, 0.69);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.2505, 1.80, 0.69);
	glTexCoord2d(0.7, 1.0); glVertex3d(-0.2505, 1.90, 0.79);
      }
      glEnd();
      

      /** The lamp **/
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glColor4f(0.9, 0.9, 1.0, 0.5);
      glPushMatrix();
      {
	glTranslated(0.0, 2.25, 0.8);
	gluSphere(quadric, 0.02, 8, 8);
      }
      glPopMatrix();
      glDisable(GL_BLEND);


      /* The cabin second block **/
      glColor3f(0.7, 0.7, 0.4);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_CABIN2]);

      /* Drawing top part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 0.0, 1.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.18, 2.05, 0.95);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.18, 1.37, 0.95);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.18, 1.37, 0.95);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.18, 2.05, 0.95);
      }
      glEnd();

      /* Drawing right part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(1.0, 0.0, 0.0);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.18, 1.37, 0.95);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.18, 1.37, 0.80);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.18, 2.05, 0.80);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.18, 2.05, 0.95);
      }
      glEnd();

      /* Drawing left part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-1.0, 0.0, 0.0);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.18, 2.05, 0.95);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.18, 2.05, 0.80);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.18, 1.37, 0.80);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.18, 1.37, 0.95);
      }
      glEnd();

      /* Drawing back part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, -1.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.18, 1.37, 0.95);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.18, 1.37, 0.80);
	glTexCoord2d(1.0, 0.0); glVertex3d( 0.18, 1.37, 0.80);
	glTexCoord2d(1.0, 1.0); glVertex3d( 0.18, 1.37, 0.95);
      }
      glEnd();

      /* Drawing frontal part */
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 1.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.18, 2.05, 0.95);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.18, 2.05, 0.80);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.18, 2.05, 0.80);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.18, 2.05, 0.95);
      }
      glEnd();


      /** Chimneys **/
      glColor3f(0.3, 0.3, 0.3);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_CHIMNEY]);
      glPushMatrix();
      {
	glTranslated(0.0, 1.61, 0.95);
	gluCylinder(quadric, 0.07, 0.03, 0.15, 16, 8);

	glTranslated(0.0, 0.20, 0.00);
	gluCylinder(quadric, 0.07, 0.03, 0.15, 16, 8);
      }
      glPopMatrix();


      /** The frontal gun **/
      /* Drawing base */
      glColor3f(0.3, 0.3, 0.3);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_GUNBASE]);
      glPushMatrix();
      {
	glTranslated(0.0, 3.1, 0.60);
	gluCylinder(quadric, 0.2, 0.2, 0.07, 32, 8);

	glTranslated(0.0, 0.0, 0.07);
	gluDisk(quadric, 0.0, 0.2, 32, 8);
      }
      glPopMatrix();

      /* Drawing support */
      glColor3f(0.1, 0.1, 0.1);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_GUN]);
      glPushMatrix();
      {
	glTranslated(0.0, 3.1, 0.69);
	glScaled(0.16, 0.16, 0.04);
	glutSolidCube(1.0);
      }
      glPopMatrix();

      /* Drawing gun itself */
      glPushMatrix();
      {
	glTranslated(-0.04, 2.97, 0.57);
	glRotated(-50.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.037, 0.037, 0.5, 16, 8);

	glTranslated( 0.08, 0.0, 0.0);
	gluCylinder(quadric, 0.037, 0.037, 0.5, 16, 8);
      }
      glPopMatrix();


      /** The back gun **/
      glTranslated(0.0, 3.7, 0.0);
      glRotated(180.0, 0.0, 0.0, 1.0);

      /* Drawing base */
      glColor3f(0.3, 0.3, 0.3);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_GUNBASE]);
      glPushMatrix();
      {
	glTranslated(0.0, 3.1, 0.60);
	gluCylinder(quadric, 0.2, 0.2, 0.07, 32, 8);

	glTranslated(0.0, 0.0, 0.07);
	gluDisk(quadric, 0.0, 0.2, 32, 8);
      }
      glPopMatrix();

      /* Drawing support */
      glColor3f(0.1, 0.1, 0.1);
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[TV_GUN]);
      glPushMatrix();
      {
	glTranslated(0.0, 3.1, 0.69);
	glScaled(0.16, 0.16, 0.04);
	glutSolidCube(1.0);
      }
      glPopMatrix();

      /* Drawing gun itself */
      glPushMatrix();
      {
	glTranslated(-0.04, 2.97, 0.57);
	glRotated(-50.0, 1.0, 0.0, 0.0);
	gluCylinder(quadric, 0.037, 0.037, 0.5, 16, 8);

	glTranslated( 0.08, 0.0, 0.0);
	gluCylinder(quadric, 0.037, 0.037, 0.5, 16, 8);
      }
      glPopMatrix();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * VESSEL EMISSIVE PARTS
 */
void createEmissivePartsVessel(void)
{
  glNewList(EMISSIVE_PARTS_VESSEL, GL_COMPILE);
  {
    /* Creating quadric object */
    GLUquadricObj * quadric = gluNewQuadric();

    /* Vessel material colors */
    GLfloat vfVesselSpecular[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat vfVesselEmission[] = { 0.8, 0.8, 0.8, 1.0 };
    GLfloat  fVesselShininess  = 70;


    /* Setting material colors */
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vfVesselSpecular);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, vfVesselEmission);
    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, fVesselShininess);

    glPushMatrix();
    {
      /* Translating */
      glTranslated(0.0, 0.0, -0.15);


      /** The windows **/
      /* Drawing frontal window */
      glColor3f(0.9, 0.9, 1.0);
      glBegin(GL_POLYGON);
      {
	glNormal3d(0.0, 1.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d( 0.24, 2.301, 0.79);
	glTexCoord2d(0.0, 0.0); glVertex3d( 0.24, 2.301, 0.69);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.24, 2.301, 0.69);
	glTexCoord2d(1.0, 1.0); glVertex3d(-0.24, 2.301, 0.79);
      }
      glEnd();

      /* Drawing right lateral window */
      glBegin(GL_POLYGON);
      {
	glNormal3d(1.0, 0.0, 0.0);
	glTexCoord2d(0.3, 1.0); glVertex3d(0.2505, 1.90, 0.79);
	glTexCoord2d(0.0, 0.0); glVertex3d(0.2505, 1.80, 0.69);
	glTexCoord2d(1.0, 0.0); glVertex3d(0.2505, 2.29, 0.69);
	glTexCoord2d(1.0, 1.0); glVertex3d(0.2505, 2.29, 0.79);
      }
      glEnd();

      /* Drawing left lateral window */
      glBegin(GL_POLYGON);
      {
	glNormal3d(-1.0, 0.0, 0.0);
	glTexCoord2d(0.0, 1.0); glVertex3d(-0.2505, 2.29, 0.79);
	glTexCoord2d(0.0, 0.0); glVertex3d(-0.2505, 2.29, 0.69);
	glTexCoord2d(1.0, 0.0); glVertex3d(-0.2505, 1.80, 0.69);
	glTexCoord2d(0.7, 1.0); glVertex3d(-0.2505, 1.90, 0.79);
      }
      glEnd();


      /** The lamp **/
      glColor3f(0.9, 0.9, 1.0);
      glPushMatrix();
      {
	glTranslated(0.0, 2.25, 0.8);
	gluSphere(quadric, 0.02, 8, 8);
      }
      glPopMatrix();
    }
    glPopMatrix();


    /* Deleting quadric object */
    gluDeleteQuadric(quadric);
  }
  glEndList();
}


/**
 * SUN
 */
void createSun(void)
{
  /* Loading textures of sun */
  generateTexturesSun();


  glNewList(SUN, GL_COMPILE);
  {
    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    /* Enable blend for transparency */
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);

    /* Drawing sun */
    /* Inner sphere */
    glColor4d(1.0, 1.0, 0.0, 1.0);
    glBindTexture(GL_TEXTURE_2D, vuiTexturesSun[TN_INNER]);
    glutSolidSphere(2.0, 32, 32);

    /* Outer sphere */
    glColor4d(0.7, 0.4, 0.2, 0.4);
    glBindTexture(GL_TEXTURE_2D, vuiTexturesSun[TN_OUTTER]);
    glutSolidSphere(2.5, 32, 32);

    /* Restoring defaults */
    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
  }
  glEndList();
}


/**
 * MOON and STARS
 */
void createMoon(void)
{
  /* Loading textures of moon */
  generateTexturesMoon();


  glNewList(MOON, GL_COMPILE);
  {
    /* Setting texture environment */
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);

    /* Enable blend for transparency */
    glDisable(GL_DEPTH_TEST);

    /* Drawing moon */
    glColor3f(1.0, 1.0, 1.0);
    glBindTexture(GL_TEXTURE_2D, vuiTexturesMoon[TM_SURFACE]);
    glutSolidSphere(1.0, 16, 16);

    /* Restoring Emission */
    glEnable(GL_DEPTH_TEST);
  }
  glEndList();
}



/**
 *
 */
void generateTexturesTable(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_TABLE, vuiTexturesTable);


  for (textureIdx = 0; textureIdx < N_TEXTURES_TABLE; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesTable[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesTable[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}


/**
 *
 */
void generateTexturesRaft(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_RAFT, vuiTexturesRaft);


  for (textureIdx = 0; textureIdx < N_TEXTURES_RAFT; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesRaft[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesRaft[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}


/**
 *
 */
void generateTexturesBoat(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_BOAT, vuiTexturesBoat);


  for (textureIdx = 0; textureIdx < N_TEXTURES_BOAT; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesBoat[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesBoat[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}


/**
 *
 */
void generateTexturesSubmarine(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_SUBMARINE, vuiTexturesSubmarine);


  for (textureIdx = 0; textureIdx < N_TEXTURES_SUBMARINE; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSubmarine[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesSubmarine[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}


/**
 *
 */
void generateTexturesVessel(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_VESSEL, vuiTexturesVessel);


  for (textureIdx = 0; textureIdx < N_TEXTURES_VESSEL; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesVessel[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesVessel[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}



/**
 *
 */
void generateTexturesSun(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_SUN, vuiTexturesSun);


  for (textureIdx = 0; textureIdx < N_TEXTURES_SUN; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesSun[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesSun[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}



/**
 *
 */
void generateTexturesMoon(void)
{
  int textureIdx;
  glGenTextures(N_TEXTURES_MOON, vuiTexturesMoon);


  for (textureIdx = 0; textureIdx < N_TEXTURES_MOON; ++textureIdx)
    {
      glBindTexture(GL_TEXTURE_2D, vuiTexturesMoon[textureIdx]);

      ppmImage_t * image = imageLoad(vpcTexturesNamesMoon[textureIdx]);
      if (image == NULL)
	{
	  fprintf(stderr, "Error reading a texture.\n");
	  exit(-1);
	}

      int gluerr =
	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image->width, image->height,
			  GL_RGB, GL_UNSIGNED_BYTE, image->data);
      if(gluerr)
	{
	  fprintf(stderr, "GLULib%s\n", gluErrorString(gluerr));
	  exit(-1);
	}

      imageFree(image);
    }
}
