// fenix@io.com: vertex arrays

/*
Copyright (C) 1996-1997 Id Software, Inc.

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 "quakedef.h"
#include "gl_rva.h"



cvar_t  r_vertex_arrays = { "r_vertex_arrays", "0" };

qboolean is_vertex_arrays_supported = false;

vavertex_t* global_vertex_array;
unsigned*   global_indice_array;

int global_vertex_array_size;
int global_indice_array_size;

int mode_table[] = {
    /* R_POINTS         */ GL_POINTS,
    /* R_LINES          */ GL_LINES,
    /* R_LINE_STRIP     */ GL_LINE_STRIP,
    /* R_LINE_LOOP      */ GL_LINE_LOOP,
    /* R_TRIANGLES      */ GL_TRIANGLES,
    /* R_TRIANGLE_STRIP */ GL_TRIANGLE_STRIP,
    /* R_TRIANGLE_FAN   */ GL_TRIANGLE_FAN,
    /* R_QUADS          */ GL_QUADS,
    /* R_QUAD_STRIP     */ GL_QUAD_STRIP,
    /* R_POLYGON        */ GL_POLYGON        
};


qboolean color3_enabled;
qboolean color4_enabled;
qboolean texcoord2_enabled;
qboolean vertex2_enabled;
qboolean vertex3_enabled;
vavertex_t* current_vertex_array;



/* R_VertexArray
 ****************************************************************************/
void R_VertexArray(vavertex_t* va, unsigned fields)
{
   current_vertex_array = va;

   if (fields & R_VERTEX3) {
      glEnableClientState(GL_VERTEX_ARRAY);
      glVertexPointer(3, GL_FLOAT, sizeof(vavertex_t), &va->x);
      vertex2_enabled = false;
      vertex3_enabled = true;
   }
   else if (fields & R_VERTEX2) {
      glEnableClientState(GL_VERTEX_ARRAY);
      glVertexPointer(2, GL_FLOAT, sizeof(vavertex_t), &va->x);
      vertex2_enabled = true;
      vertex3_enabled = false;
   }
   else {
      glDisableClientState(GL_VERTEX_ARRAY);
      vertex2_enabled = false;
      vertex3_enabled = false;
   }

   if (fields & R_COLOR4) {
      glEnableClientState(GL_COLOR_ARRAY);
      glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vavertex_t), &va->r);
      color3_enabled = false;
      color4_enabled = true;
   }
   else if (fields & R_COLOR3) {
      glEnableClientState(GL_COLOR_ARRAY);
      glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(vavertex_t), &va->r);
      color3_enabled = true;
      color4_enabled = false;
   } 
   else {
      glDisableClientState(GL_COLOR_ARRAY);
      color3_enabled = false;
      color4_enabled = false;
   }

   if (fields & R_TEXCOORD2) {
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
      glTexCoordPointer(2, GL_FLOAT, sizeof(vavertex_t), &va->s);
      texcoord2_enabled = true;
   }
   else {
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
      texcoord2_enabled = false;
   }
}



/* R_DrawArray
 ****************************************************************************/
void R_DrawArray(R_MODE mode, int first, size_t count)
{
   if (is_vertex_arrays_supported && r_vertex_arrays.value) {
      glDrawArrays(mode_table[mode], first, count);
   }
   else {
      vavertex_t *varray;
      int i;

      varray = current_vertex_array;

      glBegin(mode_table[mode]);

      for (i = 0; i < count; i++) {
         if (color4_enabled) {
            glColor4ubv(&varray->r);
         }
         else if (color3_enabled) {
            glColor3ubv(&varray->r);
         }

         if (texcoord2_enabled) {
            glTexCoord2fv(&varray->s);
         }

         if (vertex3_enabled) {
            glVertex3fv(&varray->x);
         }
         else if (vertex2_enabled) {
            glVertex2fv(&varray->x);
         }

         varray++;
      }

      glEnd();
   }
}



/* R_DrawElements
 ****************************************************************************/
void R_DrawElements(R_MODE mode, size_t count, unsigned* indices)
{
   if (is_vertex_arrays_supported && r_vertex_arrays.value) {
      glDrawElements(mode_table[mode], count, GL_UNSIGNED_INT, indices);
   }
   else {
      vavertex_t *varray;
      int i;

      glBegin(mode_table[mode]);

      for (i = 0; i < count; i++) {
         varray = current_vertex_array + indices[i];

         if (color4_enabled) {
            glColor4ubv(&varray->r);
         }
         else if (color3_enabled) {
            glColor3ubv(&varray->r);
         }

         if (texcoord2_enabled) {
            glTexCoord2fv(&varray->s);
         }

         if (vertex3_enabled) {
            glVertex3fv(&varray->x);
         }
         else if (vertex2_enabled) {
            glVertex2fv(&varray->x);
         }
      }

      glEnd();
   }
}



/* R_DrawRangeElements
 ****************************************************************************/
void R_DrawRangeElements(R_MODE mode, unsigned start, unsigned end, size_t count, unsigned* indices)
{
   if (r_vertex_arrays.value) {
      //glDrawRangeElements(mode_table[mode], start, end, count, GL_UNSIGNED_INT, indices);
   }
   else {
      R_DrawElements(mode, count, indices);
   }
}





