/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD, Damien
	CALISTE, Olivier D'Astier, laboratoire L_Sim, (2001-2006)
  
	Adresses mèl :
	BILLARD, non joignable par mèl ;
	CALISTE, damien P caliste AT cea P fr.
	D'ASTIER, dastier AT iie P cnam P fr.

	Ce logiciel est un programme informatique servant à visualiser des
	structures atomiques dans un rendu pseudo-3D. 

	Ce logiciel est régi par la licence CeCILL soumise au droit français et
	respectant les principes de diffusion des logiciels libres. Vous pouvez
	utiliser, modifier et/ou redistribuer ce programme sous les conditions
	de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
	sur le site "http://www.cecill.info".

	Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
	pris connaissance de la licence CeCILL, et que vous en avez accepté les
	termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
*/

/*   LICENCE SUM UP
	Copyright CEA, contributors : Luc BILLARD and Damien
	CALISTE and Olivier D'Astier, laboratoire L_Sim, (2001-2006)

	E-mail addresses :
	BILLARD, not reachable any more ;
	CALISTE, damien P caliste AT cea P fr.
	D'ASTIER, dastier AT iie P cnam P fr.

	This software is a computer program whose purpose is to visualize atomic
	configurations in 3D.

	This software is governed by the CeCILL  license under French law and
	abiding by the rules of distribution of free software.  You can  use, 
	modify and/ or redistribute the software under the terms of the CeCILL
	license as circulated by CEA, CNRS and INRIA at the following URL
	"http://www.cecill.info". 

	The fact that you are presently reading this means that you have had
	knowledge of the CeCILL license and that you accept its terms. You can
	find a copy of this licence shipped with this software at Documentation/licence.en.txt.
*/
#include "surfaces.h"

#include <stdlib.h>
#include <math.h>

#include <opengl.h>
#include <visu_object.h>


extern int identifier_isosurfaces;

/* max nbr of chars in strings, filenames, buffers, etc... */
/* #define vgl_NLMAX (256) */
/* CAUTION: corresponding (char *) variables should have size 
   vgl_NLMAX + 1
   to accomodate final \0 */

/* max nbr of vertices for each poly in a surface (see further) */
/* #define vgl_MAX_NUM_VERTICES 50 */

/* default resources  
after having loaded a surface file 
are set as eventually previously set,
otherwise they are the following : */
/* #define vgl_INIT_surf_r  1.0f */
/* #define vgl_INIT_surf_g  0.5f */
/* #define vgl_INIT_surf_b  0.5f */
/* #define vgl_INIT_surf_a  0.75f */
/* #define vgl_INIT_surf_amb  0.2f */
/* #define vgl_INIT_surf_dif  1.0f */
/* #define vgl_INIT_surf_shi  0.5f */
/* #define vgl_INIT_surf_spe  0.5f */
/* #define vgl_INIT_surf_emi  0.0f */

static int num_polys=0, num_points;
static int *poly_surf_index;
static int *poly_num_vertices;
static int **poly_vertices;
static double **poly_points;
static double **poly_normals;

static int *polygon_number;
static int **any_pointer;
static double *any_z;

/* static int nsurf_save = 0; */
/* static char **surfnom_save; */
/* static float *surf_r_save, *surf_g_save, *surf_b_save, *surf_a_save; */
/* static float *surf_amb_save, *surf_dif_save, *surf_shi_save,  */
/*   *surf_spe_save, *surf_emi_save; */
/* static int * surf_draw_flag; */

static GLuint lists_location = 0;

static double mat[16];
/* static float *surf_r, *surf_g, *surf_b, *surf_a; */
/* static float *surf_amb, *surf_dif, *surf_shi, */
/*    *surf_spe, *surf_emi; */
static int nsurf = 0;
static char **surfnom;

static float local_box[6];
static float inverted_local_box_matrix[3][3];
static float transform_box_matrix[3][3];

static GHashTable *isosurfaces_resources = NULL;

static void change_the_box(double *vector_from, double *vector_to);


gboolean isosurfaces_read_resources(gchar **lines, int nbLines, int position, GString *errorMessage)
{
  gchar surf_name[MAX_LINE_LENGTH];
  surf_res res, *res2;

  if(sscanf(lines[0], "%s %d %f %f %f %f %f %f %f %f %f\n", 
	    surf_name, &res.rendered, &res.material[0], &res.material[1],
	    &res.material[2], &res.material[3], &res.material[4], &res.material[5],
	    &res.material[6], &res.material[7], &res.material[8]) != 11)
      return FALSE;

  res2 = isosurfaces_resources_get(surf_name);
  *res2 = res;
  DBG_fprintf(stderr, "Isosurfaces : resources found for surface '%s'\n", surf_name);

  return TRUE;
}

void isosurfaces_count_resources(gpointer key, gpointer value, gpointer user_data)
{
  int *n = user_data;
  
  (*n)++;
}

void isosurfaces_export_one_surf_resources(gpointer key, gpointer value, gpointer user_data)
{
  GString *data = user_data;
  surf_res *res = isosurfaces_resources_get(key);

  g_string_append_printf(data, "isosurface_property[gtk]:\n");
  g_string_append_printf(data, "   %s %d %f %f %f %f %f %f %f %f %f\n",
			 (char *)key, res->rendered, res->material[0], res->material[1],
			 res->material[2], res->material[3], res->material[4], res->material[5],
			 res->material[6], res->material[7], res->material[8]);
}
			 

gboolean isosurfaces_export_resources(GString *data, int *nbLinesWritten)
{
  int n;
 
  if(isosurfaces_resources != NULL)
    {
      g_hash_table_foreach(isosurfaces_resources, isosurfaces_count_resources, &n);
      g_hash_table_foreach(isosurfaces_resources, isosurfaces_export_one_surf_resources, data);

      *nbLinesWritten += 2*n;     
    }
 
  return TRUE;
}

gpointer isosurfaces_resources_get(const gchar *surf_name)
{
  surf_res *res;
  if(surf_name == NULL)
    {
      DBG_fprintf(stderr, "WARNING : isosurfaces_resources_get called with NULL parameter\n");
      return NULL;
    }
  if(strcmp("", surf_name) == 0)
    {
      DBG_fprintf(stderr, "WARNING : isosurfaces_resources_get called with empty parameter\n");
      return NULL;
    }
  if(isosurfaces_resources == NULL)
    {
      DBG_fprintf(stderr, "Isosurfaces : initializing new hash table to store global resources\n");
      isosurfaces_resources = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
    }
  
  if((res = g_hash_table_lookup(isosurfaces_resources, surf_name)) == NULL)
    {      
      gchar *key = g_strdup(surf_name);
      res = g_malloc(sizeof(surf_res));
      res->rendered = FALSE;
      res->material[0] = 1.0f;
      res->material[1] = 0.5f;
      res->material[2] = 0.5f;
      res->material[3] = 0.75f;
      res->material[4] = 0.2f;
      res->material[5] = 1.0f;
      res->material[6] = 0.5f;
      res->material[7] = 0.5f;
      res->material[8] = 0.0f;

      DBG_fprintf(stderr, "Isosurfaces : registering new resources for surface %s\n", surf_name);

      g_hash_table_insert(isosurfaces_resources, key, res);
    }
      
  return res;
}

void isoSurfacesSet_fitToBox(VisuData *data)
{
  enum
    {
      _DXX = 0,
      _DYX,
      _DYY,
      _DZX,
      _DZY,
      _DZZ
    };
  int i,j;
  float boxCoordinatestoXYZ[3][3];

  g_return_if_fail(data);

  DBG_fprintf(stderr, "Isosurfaces : change the current box to fit to %p.\n", (gpointer) data);

  inverted_local_box_matrix[0][0] = 1 / local_box[_DXX];
  inverted_local_box_matrix[0][1] = - local_box[_DYX] / local_box[_DXX] / local_box[_DYY];
  inverted_local_box_matrix[0][2] 
    = - ((local_box[_DZX] / local_box[_DXX] -
	  local_box[_DYX] * local_box[_DZY] / 
	  local_box[_DXX] / local_box[_DYY] ) /
	 local_box[_DZZ] );
  inverted_local_box_matrix[1][0] = 0.;
  inverted_local_box_matrix[1][1] = 1 / local_box[_DYY];
  inverted_local_box_matrix[1][2] = - local_box[_DZY] /
    local_box[_DYY] / local_box[_DZZ];
  inverted_local_box_matrix[2][0] = 0.;
  inverted_local_box_matrix[2][1] = 0.;
  inverted_local_box_matrix[2][2] = 1 / local_box[_DZZ];

  visuDataGet_boxMatrix(data, boxCoordinatestoXYZ);
  for(i=0; i<3; i++)
    for(j=0; j<3; j++)
      transform_box_matrix[i][j] =
	(boxCoordinatestoXYZ[i][0]*inverted_local_box_matrix[0][j] +
	 boxCoordinatestoXYZ[i][1]*inverted_local_box_matrix[1][j] +
	 boxCoordinatestoXYZ[i][2]*inverted_local_box_matrix[2][j]);

  for (i = 0; i < num_points; i++)
    {
      double old_poly_points[3], old_poly_normals[3];	     
      for(j=0; j<3; j++)
	{
	  old_poly_points[j] = poly_points[i][j];
	  old_poly_normals[j] = poly_normals[i][j];
	}
      change_the_box(old_poly_points, poly_points[i]);
      change_the_box(old_poly_normals, poly_normals[i]);
    }
}  

/**
 * change_the_box:
 * @vector_from: 
 * @vector_to: 
 * 
 * 
 **/
static void change_the_box(double *vector_from, double *vector_to)
{
  int i, j;

  if(vector_from == NULL || vector_to == NULL)
    return;

   for (i = 0; i < 3; i++)
    {
      vector_to[i] = 0.;
      for (j = 0; j < 3; j++)
	vector_to[i] += transform_box_matrix[i][j] * vector_from[j];
    }
}

static void material(const surf_res *res) {
   float mm[4];
   
   mm[3] = res->material[3];
   
   mm[0] = res->material[4]*res->material[0];
   mm[1] = res->material[4]*res->material[1];
   mm[2] = res->material[4]*res->material[2];
   glMaterialfv(GL_FRONT, GL_AMBIENT, mm);
   mm[0] = res->material[5]*res->material[0];
   mm[1] = res->material[5]*res->material[1];
   mm[2] = res->material[5]*res->material[2];
   glMaterialfv(GL_FRONT, GL_DIFFUSE, mm);
   glMaterialf(GL_FRONT, GL_SHININESS, res->material[6]*128.0f);
   mm[0] = res->material[7];
   mm[1] = res->material[7];
   mm[2] = res->material[7];
   glMaterialfv(GL_FRONT, GL_SPECULAR, mm);
   mm[0] = res->material[8]*res->material[0];
   mm[1] = res->material[8]*res->material[1];
   mm[2] = res->material[8]*res->material[2];
   glMaterialfv(GL_FRONT, GL_EMISSION, mm);
}

/* void update_surf_mat(void) { */
/*    int i; */
/*    for(i=0; i<nsurf; i++) material(i); */
/* } */

/* static void install_saved() { */
/*    int i; */
   
/*    if(nsurf_save) { */
/*       (void)free(surfnom_save); */
/*       (void)free(surf_r_save); */
/*       (void)free(surf_g_save); */
/*       (void)free(surf_b_save); */
/*       (void)free(surf_a_save); */
/*       (void)free(surf_amb_save); */
/*       (void)free(surf_dif_save); */
/*       (void)free(surf_shi_save); */
/*       (void)free(surf_spe_save); */
/*       (void)free(surf_emi_save); */
/*    } */
   
/*    surfnom_save = g_malloc(nsurf*sizeof(char *)); */
/*    for(i=0; i<nsurf; i++) { */
/*       surfnom_save[i] = g_malloc((vgl_MAX_SURF_NAME_LENGTH + 1)*sizeof(char)); */
/*       (void)strncpy(surfnom_save[i], surfnom[i],  */
/*          vgl_MAX_SURF_NAME_LENGTH); */
/*       surfnom[i][vgl_MAX_SURF_NAME_LENGTH] = 0;  */
/*    } */
/*    surf_r_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_g_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_b_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_a_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_amb_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_dif_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_shi_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_spe_save = g_malloc(nsurf*sizeof(float)); */
/*    surf_emi_save = g_malloc(nsurf*sizeof(float)); */
/*    for(i=0; i<nsurf; i++) { */
/*       surf_r_save[i] = surf_r[i]; */
/*       surf_g_save[i] = surf_g[i]; */
/*       surf_b_save[i] = surf_b[i]; */
/*       surf_a_save[i] = surf_a[i]; */
/*       surf_amb_save[i] = surf_amb[i]; */
/*       surf_dif_save[i] = surf_dif[i]; */
/*       surf_shi_save[i] = surf_shi[i]; */
/*       surf_spe_save[i] = surf_spe[i]; */
/*       surf_emi_save[i] = surf_emi[i]; */
/*    } */
/*    nsurf_save = nsurf; */
/* } */


/* static void scan_saved(void) { */
/*    int i; */

/*    for(i = 0; i < nsurf; i++) { */
/*       int k; */
/*       for(k = 0; k < nsurf_save; k++) { */
/*          if(!strcmp(surfnom[i], surfnom_save[k])) { */
/*             surf_r[i] = surf_r_save[k]; */
/*             surf_g[i] = surf_g_save[k]; */
/*             surf_b[i] = surf_b_save[k]; */
/*             surf_a[i] = surf_a_save[k]; */
/*             surf_amb[i] = surf_amb_save[k]; */
/*             surf_dif[i] = surf_dif_save[k]; */
/*             surf_shi[i] = surf_shi_save[k]; */
/*             surf_spe[i] = surf_spe_save[k]; */
/*             surf_emi[i] = surf_emi_save[k]; */
/*             break; */
/*          } */
/*       } */
/*    } */
   
/* } */

void debug()
{
/*   int i, j; */
/* /\*   fprintf(stdout, "(num_polys:%d)(nsurf:%d)\n", num_polys, nsurf); *\/ */
/* /\*   for(i=0; i<nsurf; i++) *\/ */
/* /\*     fprintf(stdout, "%d : %s %d\n", i, surfnom[i], surf_draw_flag[i]); *\/ */
/* /\*   for(i=0; i<num_polys; i++) *\/ */
/* /\*     { *\/ */
/* /\*       fprintf(stdout, "poly_surf_index[%d]=%d, poly_num_vertices[%d]=%d", *\/ */
/* /\* 	      i, poly_surf_index[i], i, poly_num_vertices[i]); *\/ */
/* /\*       for(j=0; j<poly_num_vertices[i]; j++) *\/ */
/* /\* 	fprintf(stdout, " poly_vertices[%d][%d]=%d", i, j, poly_vertices[i][j]); *\/ */
/* /\*       fprintf(stdout, "\n"); *\/ */
/* /\*     } *\/ */
/*   fprintf(stdout, "num_points:%d\n", num_points); */
/*   for(i=0; i<num_points; i++) */
/*     { */
/*       for(j=0; j<3; j++) */
/* 	fprintf(stdout, "poly_points[%d][%d]=%f ", i, j, poly_points[i][j]); */
/*       for(j=0; j<3; j++) */
/* 	fprintf(stdout, "poly_normals[%d][%d]=%f ", i, j, poly_normals[i][j]); */
/*       fprintf(stdout, "\n"); */
/*       fflush(stdout); */
/*     } */
/*   exit(0); */
}

void freeSurf()
{
  if(nsurf) {
    g_free(poly_surf_index);
    g_free(poly_num_vertices);
    g_free(poly_vertices);
    g_free(poly_points); 
    g_free(poly_normals);
    g_free(polygon_number);   
    g_free(any_pointer);          
    g_free(any_z);
    g_free(surfnom);
    nsurf = 0;
  }   
}

/* errors are appended in buf.
   buf can be null. */
/* returns: 0 in case of success
   n != 0 otherwise */
gboolean vgl_load_surfaces(const char *file, GString *buf)
{
  gchar **line_split = NULL;
  GIOChannel* surf_file;
  GError *glib_error = NULL;
  GString *current_line = g_string_new("");
  int line_number = 0;
  double dxx=0, dyx=0, dyy=0;
  double dzx=0, dzy=0, dzz=0;
  int file_nsurfs=0, file_npolys=0, file_npoints=0;
  int npolys_loaded=0, npoints_loaded=0;
  int i,j,k;
  int sum_polys=0, sum_points=0;
  int pouet;

  DBG_fprintf(stderr, _("Isosurfaces : trying to load %s file using new fashion\n"), file);

  if((surf_file = g_io_channel_new_file(file, "r", NULL)) == NULL)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Cannot open file %s to load surfaces", file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }

  

  /*   DBG_fprintf(stderr, "File opened\n"); */
  line_number++;  

  if((pouet = g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error)) != G_IO_STATUS_NORMAL)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }
      
  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  line_number++;

  if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }

  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  line_number++;

  if(sscanf(current_line->str, "%lf %lf %lf", &dxx, &dyx, &dyy) != 3)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Line %d of file %s doesn't match the [float, float, float] pattern", line_number, file);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }
      
  if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }

  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  line_number++;

  if(sscanf(current_line->str, "%lf %lf %lf", &dzx, &dzy, &dzz) != 3)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Line %d of file %s doesn't match the [float, float, float] pattern", line_number, file);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }
      
  if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }

  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  line_number++;

  if(sscanf(current_line->str, "%d %d %d", &file_nsurfs, &file_npolys, &file_npoints) != 3)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Line %d of file %s doesn't match the [int, int, int] pattern", line_number, file);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }

  if(file_nsurfs <= 0 || file_npolys <= 0 || file_npoints <= 0)
    {
      if(buf != NULL) 
	g_string_append_printf(buf, "Line %d of file %s contains invalid parameters : negative integers", line_number, file);
      g_io_channel_unref(surf_file);
      g_string_free(current_line, TRUE);
      return FALSE;
    }

  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  line_number++;

  freeSurf();   

  local_box[0] = dxx;
  local_box[1] = dyx;
  local_box[2] = dyy;
  local_box[3] = dzx;
  local_box[4] = dzy;
  local_box[5] = dzz;
/*   init_transform_box_matrix(); */
   
  nsurf = file_nsurfs;
  num_polys = file_npolys;
  num_points = file_npoints;

  surfnom = g_malloc(nsurf*sizeof(char *));

  /* for each of the num_polys polygons will contain the surf value
     to which it belongs */
  poly_surf_index = g_malloc(num_polys*sizeof(int));

  /* for each of the num_polys polygons will contain the number
     of vertices in it */
  poly_num_vertices = g_malloc(num_polys*sizeof(int));

  /* for each of the num_polys polygons will contain the indices
     of vertices in it */   
  poly_vertices = g_malloc(num_polys*sizeof(int *));

  /* for each of the num_points,
     poly_points[][0] = x
     poly_points[][1] = y
     poly_points[][2] = z
  */ 
  poly_points = g_malloc(num_points*sizeof(double *));
  poly_points[0] = g_malloc(3*num_points*sizeof(double));
  for(i=0; i<num_points; i++)
    poly_points[i] = poly_points[0] + i * 3;

  /* for each of the num_points,
     poly_normals[][0] = nx
     poly_normals[][1] = ny
     poly_normals[][2] = nz
     where nx, ny, nz are the coordinates of the normal at the point
  */  
  poly_normals = g_malloc(num_points*sizeof(double *));
  poly_normals[0] = g_malloc(3*num_points*sizeof(double));
  for(i=0; i<num_points; i++)
    poly_normals[i] = poly_normals[0] + i * 3;

  /* auxiliary arrays used for sorting */      
  polygon_number = g_malloc(num_polys*sizeof(int));
  any_pointer = g_malloc(num_polys*sizeof(int *));
  /* recall: any_pointer[0] not allocated */
  any_z = g_malloc(num_polys*sizeof(double));

/*   surf_draw_flag = g_malloc0(nsurf*sizeof(int)); */

  /* For each surf */
  for(i=0; i<nsurf; i++) 
    {
      int surf_npolys=0, surf_npoints=0;
      gchar *surfnom_buf;

      /* Get the first line that should contain the surf name */
      if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
	{
	  if(buf != NULL) 
	    g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
	  g_io_channel_unref(surf_file);
	  g_string_free(current_line, TRUE);
	  freeSurf();
	  return FALSE;
	}
       
      /*        DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
      line_number++;

      surfnom_buf = g_strdup(current_line->str);
      g_strdelimit(surfnom_buf, "\n", ' ');       
      g_strstrip(surfnom_buf);

      /*        /\* Check for utf-8 *\/ */
      /*        if(!g_utf8_validate(surfnom_buf, -1, NULL)) */
      /* 	 { */
      /* 	   if(buf != NULL)  */
      /* 	     g_string_append_printf(buf, "Line %d of file %s is not in utf-8 format", line_number, file); */
      /* 	   g_io_channel_unref(surf_file); */
      /* 	   g_string_free(current_line, TRUE); */
      /* 	   return FALSE; */
      /* 	 } */

      surfnom[i] = surfnom_buf;

      /* Get the second line that should contain current surf' npolys & npoints */
      if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
	{
	  if(buf != NULL) 
	    g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
	  g_io_channel_unref(surf_file);
	  g_string_free(current_line, TRUE);
	  freeSurf();
	  return FALSE;
	}
       
      /*        DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
      line_number++;

      if(sscanf(current_line->str, "%d %d", &surf_npolys, &surf_npoints) != 2 
	 || surf_npolys <= 0 || surf_npoints <= 0)
	{
	  if(buf != NULL) 
	    g_string_append_printf(buf, "Line %d of file %s doesn't match the [positive int, positive int] required pattern", line_number, file);
	  g_io_channel_unref(surf_file);
	  g_string_free(current_line, TRUE);
	  freeSurf();
	  return FALSE;
	}

      sum_polys += surf_npolys;
      if(sum_polys > file_npolys)
	{
	  if(buf != NULL) 
	    g_string_append_printf(buf, "Error on line %d of file %s. Check npolys on line number 2.", line_number, file);
	  g_io_channel_unref(surf_file);
	  g_string_free(current_line, TRUE);
	  freeSurf();
	  return FALSE;
	}

      sum_points += surf_npoints;
      if(sum_points > file_npoints)
	{
	  if(buf != NULL) 
	    g_string_append_printf(buf, "Error on line %d of file %s. Check npoints on line number 2.", line_number, file);
	  g_io_channel_unref(surf_file);
	  g_string_free(current_line, TRUE);
	  freeSurf();
	  return FALSE;
	}

      for(j=0; j<surf_npolys; j++)
	{
	  int nvertex=0, nvertex_i=0;

	  gchar **split_line;
	   
	  if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
	    {
	      if(buf != NULL) 
		g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
	      g_io_channel_unref(surf_file);
	      g_string_free(current_line, TRUE);
	      freeSurf();
	      return FALSE;
	    }
       
	  /* 	   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
	  line_number++;

	  split_line = g_strsplit_set(current_line->str, " ", -1);

	  for(k=0; split_line[k] != NULL; k++)
	    {
	      if(g_ascii_strcasecmp(split_line[k], "") == 0) 
		continue;	       
	      if(nvertex == 0)
		{
		  if(sscanf(split_line[k], "%d", &nvertex) != 1 || nvertex < 3)
		    {
		      if(buf != NULL) 
			g_string_append_printf(buf, "Line %d of file %s must begin by an int.", line_number, file);
		      g_io_channel_unref(surf_file);
		      g_string_free(current_line, TRUE);
		      freeSurf();
		      return FALSE;
		    }
		  poly_num_vertices[npolys_loaded] = nvertex;
		  poly_vertices[npolys_loaded] = g_malloc(nvertex*sizeof(double));
		  poly_surf_index[npolys_loaded] = i;
		  npolys_loaded++;
		  continue;
		}		   
	      if(sscanf(split_line[k], "%d", &poly_vertices[npolys_loaded-1][nvertex_i]) != 1)
		{
		  if(buf != NULL) 
		    g_string_append_printf(buf, "Line %d of file %s doesn't match the [int > 3, ...] required pattern", line_number, file);
		  g_io_channel_unref(surf_file);
		  g_string_free(current_line, TRUE);
		  freeSurf();
		  return FALSE;
		}
	      poly_vertices[npolys_loaded-1][nvertex_i] += -1 + npoints_loaded;
	      nvertex_i++;
	      if(nvertex_i >= nvertex)
		break;
	    }
	}
 
      for(j=0; j<surf_npoints; j++) 
	{
	  if(g_io_channel_read_line_string(surf_file, current_line, NULL, &glib_error) != G_IO_STATUS_NORMAL)
	    {
	      if(buf != NULL) 
		g_string_append_printf(buf, "Cannot read line %d of file %s (glib reported '%s')", line_number, file, glib_error->message);
	      g_io_channel_unref(surf_file);
	      g_string_free(current_line, TRUE);
	      freeSurf();
	      return FALSE;
	    }
       
	  /* 	  DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
	  line_number++;

	  if(sscanf(current_line->str, "%lf %lf %lf %lf %lf %lf", 
		    &poly_points[npoints_loaded][0],
		    &poly_points[npoints_loaded][1],
		    &poly_points[npoints_loaded][2],
		    &poly_normals[npoints_loaded][0], 
		    &poly_normals[npoints_loaded][1], 
		    &poly_normals[npoints_loaded][2]) != 6) 
	    {
	      if(buf != NULL) 
		g_string_append_printf(buf, "Line %d of file %s doesn't match the [float, float, float, float, float, float] required pattern", line_number, file);
	      g_io_channel_unref(surf_file);
	      g_string_free(current_line, TRUE);
	      freeSurf();
	      return FALSE;	      
	    }

/* 	  if(fit_to_box) */
/* 	    { */
/* 	      double old_poly_points[3], old_poly_normals[3];	      */
/* 	      for(k=0; k<3; k++) */
/* 		{ */
/* 		  old_poly_points[k] = poly_points[npoints_loaded][k]; */
/* 		  old_poly_normals[k] = poly_normals[npoints_loaded][k]; */
/* 		} */
/* 	      change_the_box(old_poly_points, poly_points[npoints_loaded]); */
/* 	      change_the_box(old_poly_normals, poly_normals[npoints_loaded]); */
/* 	    } */
	  npoints_loaded++;
	}
    }

  g_io_channel_unref(surf_file);
       
  /*    debug(); */

/*   surf_r = g_malloc(nsurf*sizeof(float)); */
/*   surf_g = g_malloc(nsurf*sizeof(float)); */
/*   surf_b = g_malloc(nsurf*sizeof(float)); */
/*   surf_a = g_malloc(nsurf*sizeof(float)); */
/*   surf_amb = g_malloc(nsurf*sizeof(float)); */
/*   surf_dif = g_malloc(nsurf*sizeof(float)); */
/*   surf_shi = g_malloc(nsurf*sizeof(float)); */
/*   surf_spe = g_malloc(nsurf*sizeof(float)); */
/*   surf_emi = g_malloc(nsurf*sizeof(float)); */
   
/*   for(i=0; i<nsurf; i++) */
/*     { */
/*       surf_r[i] = vgl_INIT_surf_r; */
/*       surf_g[i] = vgl_INIT_surf_g; */
/*       surf_b[i] = vgl_INIT_surf_b; */
/*       surf_a[i] = vgl_INIT_surf_a; */
/*       surf_amb[i] = vgl_INIT_surf_amb; */
/*       surf_dif[i] = vgl_INIT_surf_dif; */
/*       surf_shi[i] = vgl_INIT_surf_shi; */
/*       surf_spe[i] = vgl_INIT_surf_spe; */
/*       surf_emi[i] = vgl_INIT_surf_emi; */
/*     } */

/*   vgl_surf_set_rendered(0, 1); */
/*   update_surf_mat(); */

  vgl_order_polygons();

  return TRUE;
}  

/* int vgl_load_surfaces_(const char *fich, GString *buf, int fit_to_box) { */
/*    FILE *in; */
/*    int ks, i, j, n, jk; */
/*    char rep[vgl_NLMAX + 2]; */
/*    int n_polys, n_points; */
/*    int num_polys_s, num_points_s; */
/*    int sum_polys, sum_points; */
/*    int nsave_pts; */
/*    double dxx, dyx, dyy, dzx, dzy, dzz; */
/*    int lineno; */
/*    double test_temp2[3], test_temp[3]; */
/*    char nomloc[1024]; */
   
/*    DBG_fprintf(stderr, _("Isosurfaces : trying to load %s file\n"), fich); */

/*    in = fopen(fich, "r"); */
/*    if(!in) { */
/*       if(buf != NULL) g_string_append_printf(buf, "Cannot open file to load surfaces"); */
/*       return 1; */
/*    }    */
   
/*    if(nsurf) install_saved(); */
   
/*    lineno = 1; */
      
/*    fgets(rep, vgl_NLMAX + 2, in); */
/*    if(feof(in)) { */
/*       fclose(in); */
/*       if(buf != NULL) g_string_append_printf(buf, "Cannot read title in surface file"); */
/*       return 1; */
/*    }  */
/*    if(rep[strlen(rep)-1] != '\n') { */
/*      fclose(in); */
/*      if(buf != NULL) g_string_append_printf(buf, "Surfaces file: 1st line too long\n"); */
/*      return 1; */
/*    } */
/*    lineno++; */
      
/*    fgets(rep, vgl_NLMAX + 2, in);  */
/*    if(rep[strlen(rep)-1] != '\n') { */
/*      fclose(in); */
/*      if(buf != NULL) g_string_append_printf(buf, "Surfaces file: 2nd line too long\n"); */
/*      return 1; */
/*    } */
/*    if(feof(in) || sscanf(rep, "%lf %lf %lf", &dxx, &dyx, &dyy) != 3 ) { */
/*       fclose(in); */
/*       if(buf != NULL) g_string_append_printf(buf, "Cannot read dxx, dyx, dyy (line 2) in surface file"); */
/*       return 1; */
/*    } */
/*    lineno++; */
      

/*    fgets(rep, vgl_NLMAX + 2, in);  */
/*    if(rep[strlen(rep)-1] != '\n') { */
/*      fclose(in); */
/*      if(buf != NULL) g_string_append_printf(buf, "Surfaces file: 3rd line too long\n"); */
/*      return 1; */
/*    } */
/*    if(feof(in) || sscanf(rep, "%lf %lf %lf", &dzx, &dzy, &dzz) != 3 ) { */
/*       fclose(in); */
/*       if(buf != NULL) g_string_append_printf(buf, "Cannot read dzx, dzy, dzz (line 3) in surface file"); */
/*       return 1; */
/*    } */
/*    local_box[0] = dxx; */
/*    local_box[1] = dyx; */
/*    local_box[2] = dyy; */
/*    local_box[3] = dzx; */
/*    local_box[4] = dzy; */
/*    local_box[5] = dzz; */
/*    lineno++; */
   
/*    if(nsurf) { */
/*      g_free(surf_emi); */
/*      g_free(surf_spe); */
/*      g_free(surf_shi); */
/*      g_free(surf_dif); */
/*      g_free(surf_amb); */
/*      g_free(surf_r); */
/*      g_free(surf_g); */
/*      g_free(surf_b); */
/*      g_free(surf_a); */
/*      for(i=0; i<num_polys; i++) */
/*        g_free(poly_vertices[i]); */
/*      g_free(surf_draw_flag); */
/*      g_free(any_z); */
/*      g_free(any_pointer);           */
/*      g_free(polygon_number);    */
/*      g_free(poly_normals[0]); */
/*      g_free(poly_normals); */
/*      g_free(poly_points[0]); */
/*      g_free(poly_points);  */
/*      g_free(poly_vertices); */
/*      g_free(poly_num_vertices); */
/*      /\* recall: any_pointer[0] not allocated *\/  */
/*      g_free(surfnom); */
/*      glDeleteLists(lists_location, nsurf); */
/*    }    */
   
/*    fgets(rep, vgl_NLMAX + 2, in);  */
/*    if(rep[strlen(rep)-1] != '\n') { */
/*       fclose(in); */
/*       if(buf != NULL) g_string_append_printf(buf, "Surfaces file: line too long\n"); */
/*       return 1; */
/*    } */
/*    if(feof(in) || sscanf(rep, "%d %d %d",  */
/*       &nsurf, &num_polys, &num_points) != 3) { */
/*       fclose(in); */
/*       if(buf != NULL)  */
/* 	g_string_append_printf(buf, "Cannot read nsurf, total_num_polys, total_num_points " */
/* 			       "(line 4) in surface file"); */
/*       return 1; */
/*    } */
/*    if(nsurf <= 0 || num_polys <= 0 || num_points <= 0) { */
/*       fclose(in); */
/*       if(buf != NULL)  */
/* 	g_string_append_printf(buf, "Needs 3 positive integers on line %d", lineno); */
/*       return 1; */
/*    }   */
/*    lineno++; */
   
/*    /\* for each of the num_polys polygons will contain the surf value */
/*       to which it belongs *\/ */
      
/*    poly_surf_index = g_malloc(num_polys*sizeof(int)); */

/*    /\* for each of the num_polys polygons will contain the number */
/*       of vertices in it *\/ */

/*    poly_num_vertices = g_malloc(num_polys*sizeof(int)); */
   
/*    /\* for each of the num_polys polygons will contain the indices */
/*       of vertices in it *\/    */
/*    poly_vertices = g_malloc(num_polys*sizeof(int *)); */

/*    poly_vertices[0] = g_malloc(vgl_MAX_NUM_VERTICES*num_polys*sizeof(int)); */

/*    for(i=0; i<num_polys; i++) poly_vertices[i] = poly_vertices[0]  */
/*       + i * vgl_MAX_NUM_VERTICES; */
   
/*    /\* for each of the num_points, */
/*       poly_points[][0] = x */
/*       poly_points[][1] = y */
/*       poly_points[][2] = z */
/*    *\/  */
/*    poly_points = g_malloc(num_points*sizeof(double *)); */

/*    poly_points[0] = g_malloc(3*num_points*sizeof(double)); */

/*    for(i=0; i<num_points; i++) */
/*       poly_points[i] = poly_points[0] + i * 3; */
   
/*    /\* for each of the num_points, */
/*       poly_normals[][0] = nx */
/*       poly_normals[][1] = ny */
/*       poly_normals[][2] = nz */
/*       where nx, ny, nz are the coordinates of the normal at the point */
/*    *\/   */
/*    poly_normals = g_malloc(num_points*sizeof(double *)); */

/*    poly_normals[0] = g_malloc(3*num_points*sizeof(double)); */

/*    for(i=0; i<num_points; i++) */
/*       poly_normals[i] = poly_normals[0] + i * 3; */
   
/*    /\* auxiliary arrays used for sorting *\/       */
/*    polygon_number = g_malloc(num_polys*sizeof(int)); */
   
/*    any_pointer = g_malloc(num_polys*sizeof(int *)); */
/*    /\* recall: any_pointer[0] not allocated *\/ */
    
/*    any_z = g_malloc(num_polys*sizeof(double)); */

/*    num_polys_s = num_polys; */
/*    num_points_s = num_points; */
/*    num_polys = 0; */
/*    num_points = 0; */
/*    nsave_pts = 0; */
 
/*    surfnom = g_malloc(nsurf*sizeof(char *)); */
   
/*    surf_draw_flag = g_malloc0(nsurf*sizeof(int)); */

/*    if((lists_location = glGenLists(nsurf)) == 0) */
/*      { */
/*        fclose(in); */
/*        if(buf != NULL) g_string_append_printf(buf, "ERROR : Can't create display lists"); */
/*        return 1; */
/*      }    */

/*    sum_polys = sum_points = 0; */

/*    init_transform_box_matrix(); */
   
/*    for(ks=0; ks<nsurf; ks++) { */
/*      char *nomloc_utf8; */
      
/*       fgets(rep, vgl_NLMAX + 2, in);  */
/*       if(rep[strlen(rep)-1] != '\n') { */
/* 	fclose(in); */
/* 	if(buf != NULL) g_string_append_printf(buf, "Surface #%d: line %d too long\n", ks+1, lineno); */
/* 	 return 1; */
/*       } */
/*       if(feof(in) || sscanf(rep, "%s", nomloc) != 1 ) { */
/*          fclose(in); */
/*          if(buf != NULL) g_string_append_printf(buf, "Cannot read name of the surface #%d" */
/*                             " (lineno = %d)", ks+1, lineno); */
/*          return 1; */
/*       } */
/*       lineno++; */
      
/*       for(jk=strlen((char *)nomloc); jk<= vgl_MAX_SURF_NAME_LENGTH; jk++)  */
/*          nomloc[jk] = ' ';      */
      
/*       surfnom[ks] = g_malloc((vgl_MAX_SURF_NAME_LENGTH + 1)*sizeof(char)); */

/*       /\* modified for v_sim : support for utf-8 *\/ */
/*       nomloc[vgl_MAX_SURF_NAME_LENGTH] = '\0'; */
/*       nomloc_utf8 = getStringInUTF8((char *)nomloc); */
/*       /\*       strncpy((char *)surfnom[ks], (char *)nomloc,  *\/ */
/*       /\*          vgl_MAX_SURF_NAME_LENGTH); *\/ */
/*       strncpy(surfnom[ks], nomloc_utf8,  */
/* 		    vgl_MAX_SURF_NAME_LENGTH); */
/*       g_free(nomloc_utf8); */
      
/*       surfnom[ks][vgl_MAX_SURF_NAME_LENGTH] = 0; */
      
/*       fgets(rep, vgl_NLMAX + 2, in);  */
/*       if(rep[strlen(rep)-1] != '\n') { */
/* 	fclose(in); */
/* 	if(buf != NULL) g_string_append_printf(buf, "Surface #%d: line %d too long\n", ks+1, lineno); */
/* 	 return 1; */
/*       } */
/*       if(feof(in) || sscanf(rep, "%d %d", &n_polys, &n_points) != 2 ) { */
/*          fclose(in); */
/* 	 if(buf != NULL) g_string_append_printf(buf,  */
/*             "Cannot read n_polys and n_points for surface #%d" */
/*                             " (lineno = %d)", ks+1, lineno); */
/*          return 1; */
/*       } */
/*       if(n_polys <= 0 || n_points <= 0) { */
/*          fclose(in); */
/*          if(buf != NULL) g_string_append_printf(buf, "Needs 2 positive integers on line %d", lineno); */
/*          return 1; */
/*       } */
/*       sum_polys += n_polys; */
/*       if(sum_polys > num_polys_s) { */
/*          fclose(in); */
/*          if(buf != NULL) g_string_append_printf(buf, "npolys on line %d\nERROR: " */
/*                             "total n_polys surely incorrect!", lineno); */
/*          return 1; */
/*       } */
/*       sum_points += n_points; */
/*       if(sum_points > num_points_s) { */
/*          fclose(in); */
/*          if(buf != NULL) g_string_append_printf(buf, "npoints on line %d\nERROR: " */
/*                             "total n_points surely incorrect!", lineno); */
/*          return 1; */
/*       } */
/*       lineno++; */
      
/*       for(i=0; i<n_polys; i++) { */
/*          int m, mm; */
/*          poly_surf_index[num_polys] = ks; */
/*          fgets(rep, vgl_NLMAX + 2, in);  */
/*          if(rep[strlen(rep)-1] != '\n') { */
/* 	   fclose(in);	    */
/* 	   if(buf != NULL) g_string_append_printf(buf, "Surface #%d: line %d too long\n", ks+1, lineno); */
/* 	    return 1; */
/*          } */
/*          if(feof(in) || sscanf(rep, "%d%n", */
/*             &poly_num_vertices[num_polys], &m) != 1 ) { */
/*             fclose(in); */
/*             if(buf != NULL) g_string_append_printf(buf,  */
/*                "Cannot read number of vertices in the poly for surface #%d" */
/*                " (lineno = %d)", ks+1, lineno); */
/*                return 1; */
/*          } */
/*          if(poly_num_vertices[num_polys] < 3) { */
/*             fclose(in); */
/*             if(buf != NULL) g_string_append_printf(buf,  */
/*                "number of vertices in the poly for surface #%d" */
/*                " should be >= 3 (lineno = %d)", ks+1, lineno); */
/*                return 1; */
/*          } */
/*          if(poly_num_vertices[num_polys] > vgl_MAX_NUM_VERTICES) { */
/*             fclose(in); */
/*             if(buf != NULL) g_string_append_printf(buf,  */
/*                "poly_num_vertices[%d] = %d > %d (surf #%d) (lineno = %d)\n" */
/*                "vgl lib needs to increase vgl_MAX_NUM_VERTICES", */
/*               i+1, poly_num_vertices[num_polys],  */
/*               vgl_MAX_NUM_VERTICES, ks+1, lineno); */
/*               return 1;    */
/*          } */
/*          for(j=0; j<poly_num_vertices[num_polys]; j++) { */
/*             if(sscanf(rep+m, "%d%n", &n, &mm) != 1) { */
/*                fclose(in); */
/*                if(buf != NULL) g_string_append_printf(buf, "Cannot read vertex #%d (surf #%d) " */
/*                "(lineno = %d)", j+1, ks+1, lineno); */
/*                return 1; */
/*             } */
/*             if(n < 1 || n > n_points) { */
/*                fclose(in); */
/*                if(buf != NULL) g_string_append_printf(buf, "Incorrect vertex #%d (surf #%d) " */
/* 	       "(lineno = %d)", j+1, ks+1, lineno); */
/*                return 1; */
/*             } */
/*             poly_vertices[num_polys][j] = n-1 + nsave_pts; */
/*             m +=mm; */
/*          } */
/*          lineno++; */
/*          num_polys++; */
/*       } */
      
/*       nsave_pts += n_points; */
      
/*       for(i=0; i<n_points; i++) { */
/*          fgets(rep, vgl_NLMAX + 2, in);  */
/*          if(rep[strlen(rep)-1] != '\n') { */
/* 	   fclose(in); */
/* 	   if(buf != NULL) g_string_append_printf(buf, "Surface #%d: line %d too long\n", ks+1, lineno); */
/* 	   return 1; */
/*          } */
/*          if(feof(in) || sscanf(rep, "%lf %lf %lf %lf %lf %lf",  */
/*             &poly_points[num_points][0], */
/*             &poly_points[num_points][1], */
/*             &poly_points[num_points][2], */
/*             &poly_normals[num_points][0],  */
/*             &poly_normals[num_points][1],  */
/*             &poly_normals[num_points][2]) != 6) { */
/*             fclose(in); */
/*             if(buf != NULL) g_string_append_printf(buf, "Cannot read coord-normals #%d (surf #%d) " */
/*             "(lineno = %d)", i+1, ks+1, lineno); */
/*             return 1; */
/*          } */
/* 	 if(fit_to_box) */
/* 	   { */
/* 	     double old_poly_points[3], old_poly_normals[3];	      */
/* 	     int i; */
/* 	     for(i=0; i<3; i++) */
/* 	       { */
/* 		 old_poly_points[i] = poly_points[num_points][i]; */
/* 		 old_poly_normals[i] = poly_normals[num_points][i]; */
/* 	       } */
/* 	     change_the_box(old_poly_points, poly_points[num_points]); */
/* 	     change_the_box(old_poly_normals, poly_normals[num_points]); */
/* 	   } */
/* 	 lineno++; */
/*          num_points++; */
/*       } */
      
/*    } */
   
/*    fclose(in); */

/*    debug(); */

   
/*    surf_r = g_malloc(nsurf*sizeof(float)); */
/*    surf_g = g_malloc(nsurf*sizeof(float)); */
/*    surf_b = g_malloc(nsurf*sizeof(float)); */
/*    surf_a = g_malloc(nsurf*sizeof(float)); */
/*    surf_amb = g_malloc(nsurf*sizeof(float)); */
/*    surf_dif = g_malloc(nsurf*sizeof(float)); */
/*    surf_shi = g_malloc(nsurf*sizeof(float)); */
/*    surf_spe = g_malloc(nsurf*sizeof(float)); */
/*    surf_emi = g_malloc(nsurf*sizeof(float)); */
   
/*    for(i=0; i<nsurf; i++) { */
/*       surf_r[i] = vgl_INIT_surf_r; */
/*       surf_g[i] = vgl_INIT_surf_g; */
/*       surf_b[i] = vgl_INIT_surf_b; */
/*       surf_a[i] = vgl_INIT_surf_a; */
/*       surf_amb[i] = vgl_INIT_surf_amb; */
/*       surf_dif[i] = vgl_INIT_surf_dif; */
/*       surf_shi[i] = vgl_INIT_surf_shi; */
/*       surf_spe[i] = vgl_INIT_surf_spe; */
/*       surf_emi[i] = vgl_INIT_surf_emi; */
/*    } */
   
/*    if(nsurf_save) scan_saved(); */

/*    vgl_surf_set_rendered(0, 1); */
/*    update_surf_mat();   */

/*    return 0; */
/* } */


static void sort_by_z(int *pointer[], double *zs, int begin, int end) {
   int i;
   int middle;
   int *temp;

   if( begin >= end ) return;
   temp = pointer[begin];
   pointer[begin] = pointer[(end+begin)/2];
   pointer[(end+begin)/2] = temp;
   middle = begin;
   for(i = begin +1; i <= end; i++) {
      if ( zs[*pointer[i]] < zs[*pointer[begin]] ) {
         temp = pointer[i];
         pointer[i] = pointer[++middle];
         pointer[middle] = temp;
      }
   }
   temp = pointer[begin];
   pointer[begin] = pointer[middle];
   pointer[middle] = temp;
   sort_by_z(pointer, zs, begin, middle-1);
   sort_by_z(pointer, zs, middle+1, end);
}


static double z_eye(int m) {
   return
      (mat[ 2]*poly_points[m][0]+
       mat[ 6]*poly_points[m][1]+
       mat[10]*poly_points[m][2]+
       mat[14]*1.)/
      (mat[ 3]*poly_points[m][0]+
       mat[ 7]*poly_points[m][1]+
       mat[11]*poly_points[m][2]+
       mat[15]*1.);
}


void vgl_order_polygons() {
   int i,j;

   DBG_fprintf(stderr, "Isosurfaces : re-ordering polygons in back to front order\n");
   
   glGetDoublev(GL_MODELVIEW_MATRIX, mat);
   
   for( i = 0; i < num_polys; i++) {
      polygon_number[i] = i;
      any_pointer[i] = &polygon_number[i];
      any_z[i] = 0.0;
      for(j=0;j < poly_num_vertices[i]; j++)
         any_z[i] += z_eye(poly_vertices[i][j]);
      any_z[i] /= poly_num_vertices[i];
   }
   
   sort_by_z(any_pointer, any_z, 0, num_polys-1);
}


void draw_surfaces(OpenGLView *view) {
   int i,j, ip, itp;
   int nb = num_polys;
   int itp_old = -1;
   surf_res *res;
   
   DBG_fprintf(stderr, "Isosurfaces : rebuilding surfaces' list\n");

   glNewList(identifier_isosurfaces, GL_COMPILE);  
   glPushMatrix();
   glDisable(GL_CULL_FACE);
   glTranslated(- view->box->dxxs2,
		- view->box->dyys2,
		- view->box->dzzs2);
   
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glEnable(GL_BLEND);   
    

   for(i = 0; i < nb; i++) {
     ip = *any_pointer[i];
     itp = poly_surf_index[ip];
     /*      if(surf_draw_flag[itp] == 0) continue; */
     if(itp != itp_old) {
       res = isosurfaces_resources_get(vgl_get_surface_name(itp+1));
       if(res->rendered == FALSE)
	 continue;
       /*          glCallList(lists_location + itp); */
       material(res);
       itp_old = itp;
     }
     glBegin(GL_POLYGON);
     for(j=0;j<poly_num_vertices[ip]; j++ ) {
       glNormal3dv(&poly_normals[poly_vertices[ip][j]][0]);
       glVertex3dv(&poly_points[poly_vertices[ip][j]][0]);
     }
     glEnd();
   }
   

   glPopMatrix();
   glEndList();  

}


void vgl_get_surfaces_number(int *surfaces_number) {
   *surfaces_number = nsurf;
}

const char * vgl_get_surface_name(int surf_number) {
   int k;
   if(surf_number < 1 || surf_number > nsurf) {
     DBG_fprintf(stderr, "WARNING : surface number %d doesn't exist", surf_number);
     return NULL;
   }
   return surfnom[surf_number-1];
}

int vgl_get_surface_index(const char *name) 
{
/*    char tmp[vgl_MAX_SURF_NAME_LENGTH + 1]; */
/*    int j, k; */
/*    strcpy(tmp, name); */
/*    for(j=strlen(tmp); j<vgl_MAX_SURF_NAME_LENGTH; j++) { */
/*        tmp[j] = ' '; */
/*    } */
/*    tmp[vgl_MAX_SURF_NAME_LENGTH] = 0; */
/*    for(k=0; k<nsurf; k++) { */
/*       if(!strcmp(tmp, surfnom[k])) { */
/*          *index = k + 1; */
/*          return; */
/*       } */
/*    } */
/*    *index = 0; */
  int i;
  for(i=0; i<nsurf; i++)
    {
      if(g_ascii_strcasecmp(vgl_get_surface_name(i+1), name))
	{
	  return i+1;
	}
    }
  return 0;
}
/* void vgl_get_surface_name_properties_bis(char *name, float *properties) */
/* { */
/*   vgl_get_surface_name_properties(name, */
/* 				  &properties[0], */
/* 				  &properties[1], */
/* 				  &properties[2], */
/* 				  &properties[3], */
/* 				  &properties[4], */
/* 				  &properties[5], */
/* 				  &properties[6], */
/* 				  &properties[7], */
/* 				  &properties[8]); */
/* } */

/* void vgl_get_surface_name_properties(char *name, */
/* float *r, float *g, float *b, float *a, */
/* float *amb, float *dif, float *shi, float *spe, float *emi) { */
/*    int k; */
/*    vgl_get_surface_index(name, &k); */
/*    if(k == 0) { */
/*       *r = -1.0f; */
/*       return; */
/*    } */
/*    *r = surf_r[k-1]; */
/*    *g = surf_g[k-1]; */
/*    *b = surf_b[k-1]; */
/*    *a = surf_a[k-1]; */
/*    *amb = surf_amb[k-1]; */
/*    *dif = surf_dif[k-1]; */
/*    *shi = surf_shi[k-1]; */
/*    *spe = surf_spe[k-1]; */
/*    *emi = surf_emi[k-1]; */
/* } */

/* void vgl_get_surface_properties_bis(int surface_number, float *properties) */
/* { */
/*   vgl_get_surface_properties(surface_number, */
/* 			     &properties[0], */
/* 			     &properties[1], */
/* 			     &properties[2], */
/* 			     &properties[3], */
/* 			     &properties[4], */
/* 			     &properties[5], */
/* 			     &properties[6], */
/* 			     &properties[7], */
/* 			     &properties[8]); */
/* } */

/* void vgl_get_surface_properties(int surface_number, */
/* float *r, float *g, float *b, float *a, */
/* float *amb, float *dif, float *shi, float *spe, float *emi) { */
/*   int k = surface_number; */
/*   if(k == 0 || k > nsurf) */
/*     { */
/*       DBG_fprintf(stderr, "WARNING : surface number %d doesn't exist", surface_number); */
/*       return; */
/*     } */
/*    *r = surf_r[k-1]; */
/*    *g = surf_g[k-1]; */
/*    *b = surf_b[k-1]; */
/*    *a = surf_a[k-1]; */
/*    *amb = surf_amb[k-1]; */
/*    *dif = surf_dif[k-1]; */
/*    *shi = surf_shi[k-1]; */
/*    *spe = surf_spe[k-1]; */
/*    *emi = surf_emi[k-1]; */
/* } */


/* void vgl_change_surface_properties_bis(int surface_number, float *properties) */
/* { */
/*   vgl_change_surface_properties(surface_number, */
/* 				properties[0], */
/* 				properties[1], */
/* 				properties[2], */
/* 				properties[3], */
/* 				properties[4], */
/* 				properties[5], */
/* 				properties[6], */
/* 				properties[7], */
/* 				properties[8]); */
/* } */

/* void vgl_change_surface_properties(int surface_number, */
/* float r, float g, float b, float a, */
/* float amb, float dif, float shi, float spe, float emi) { */
/*    int k = surface_number; */
/*   if(k == 0 || k > nsurf) */
/*     { */
/*       DBG_fprintf(stderr, "WARNING : surface number %d doesn't exist", surface_number); */
/*       return; */
/*     } */
/*    surf_r[k-1] = r; */
/*    surf_g[k-1] = g; */
/*    surf_b[k-1] = b; */
/*    surf_a[k-1] = a; */
/*    surf_amb[k-1] = amb; */
/*    surf_dif[k-1] = dif; */
/*    surf_shi[k-1] = shi; */
/*    surf_spe[k-1] = spe; */
/*    surf_emi[k-1] = emi; */
/* /\*    material(k-1); *\/ */
/* } */

/* void vgl_change_surface_name_properties(char *name, */
/* float r, float g, float b, float a, */
/* float amb, float dif, float shi, float spe, float emi) { */
/*    int k; */
/*    vgl_get_surface_index(name, &k); */
/*    if(k == 0) { */
/*       return; */
/*    } */
/*    surf_r[k-1] = r; */
/*    surf_g[k-1] = g; */
/*    surf_b[k-1] = b; */
/*    surf_a[k-1] = a; */
/*    surf_amb[k-1] = amb; */
/*    surf_dif[k-1] = dif; */
/*    surf_shi[k-1] = shi; */
/*    surf_spe[k-1] = spe; */
/*    surf_emi[k-1] = emi; */
/* /\*    material(k-1); *\/ */
/* } */

/* int vgl_surf_is_rendered(int number) */
/* { */
/*   if((number-1 < nsurf) && (number - 1 >= 0)) */
/*     return surf_draw_flag[number-1]; */
/*   else  */
/*     { */
/*       DBG_fprintf(stderr, "\nWARNING : vgl_surf_is_rendered called with invalid parameter\n\n"); */
/*       return -1; */
/*     } */
/* } */

/* void vgl_surf_set_rendered(int number, int boolean) */
/* { */
/*   int i; */
/*   DBG_fprintf(stderr,  */
/* 	      "Isosurfaces : set visibility to %d for surface number %d\n",  */
/* 	      boolean, number); */
/*   if(number == 0) */
/*     for(i=1; i<=nsurf; i++) */
/*       vgl_surf_set_rendered(i, boolean);       */
/*   else if((number-1 < nsurf) && (number - 1 >= 0)) */
/*     surf_draw_flag[number-1] = boolean; */
/*   else  */
/*     { */
/*       DBG_fprintf(stderr, "\nWARNING : vgl_surf_set_rendered called with invalid parameter\n\n"); */
/*       return; */
/*     } */
/* } */



