Logo Search packages:      
Sourcecode: v-sim version File versions  Download package

surfaces.c

/*   EXTRAITS DE LA LICENCE
      Copyright CEA, contributeurs : Luc BILLARD, Damien
      CALISTE, Olivier D'Astier, laboratoire L_Sim, (2001-2005)
  
      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-2005)

      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>
#include <visu_configFile.h>
#include <visu_tools.h>
#include <coreTools/toolMatrix.h>

#define ISOSURFACES_FLAG_POTENTIAL "# potentialValue"


typedef struct SurfacesProperties_struct
{
  /* The element (G_TYPE_INT...). */
  guint type;
  /* A pointer to the surf it belongs to. */
  Surfaces *surf;
  /* The data. */
  gpointer data;
} SurfacesProperties;

struct SurfacesOrder_struct
{
  /* The size of the allocated arrays. */
  int allocatedSize;

  /* Any_pointer[i][0:1] gives the id for surfaces and id for poly i
     in the z sorted from back to front. */
  int **any_pointer;
  /* Store the z value.
     The array is recomputed each time, but stored here to
     avoid constant malloc. */
  double *any_z;
  /* Give for all poly the id for surfaces object and the id for poly
     in this object. any_pointer elements point to that array. */
  int *polygon_number;
};

static GHashTable *isosurfaces_resources = NULL;

/* Local methods. */
gboolean isosurfaces_read_resources(gchar **lines, int nbLines, int position, GString *errorMessage);
gboolean isosurfaces_export_resources(GString *data, int *nbLinesWritten,
                              VisuData *dataObj);
void isosurfacesInit_resource(SurfaceResource *res);
void isosurfacesFree_resources(SurfaceResource *res);
void hash_free_resource(gpointer res);
static void freeSurfacesProperties(gpointer data);
static void propertiesRemoveSurf(gpointer key, gpointer value, gpointer data);
static void propertiesReallocateSurf(gpointer key, gpointer value, gpointer data);


void isosurfacesInit()
{
  VISU_ERROR_ISOSURFACES = g_quark_from_string("visu_isosurfaces");

  visuConfigFileAdd_entry(VISU_CONFIGFILE_RESOURCE,
                    "isosurface_property",
                    "Properties of a given isosurface",
                    1, isosurfaces_read_resources);
  visuConfigFileAdd_exportFunction(VISU_CONFIGFILE_RESOURCE,
                           isosurfaces_export_resources);

  isosurfaces_resources = g_hash_table_new_full(g_str_hash, g_str_equal,
                                    g_free, hash_free_resource);
}

void isosurfacesCheck_consistency(Surfaces* surf)
{
  int i, j;

  DBG_fprintf(stderr, "Isosurfaces : Check consistency.\n");

  /* Check the surface index. */
  for (i = 0; i < surf->num_polys; i++)
    g_return_if_fail(surf->poly_surf_index[i] >= 0 &&
                 surf->poly_surf_index[i] < surf->nsurf);

  /* Check vertice index. */
  for (i = 0; i < surf->num_polys; i++)
    for (j = 0; j < surf->poly_num_vertices[i]; j++)
      g_return_if_fail(surf->poly_vertices[i][j] >= 0 &&
                   surf->poly_vertices[i][j] < surf->num_points);
}

gboolean isosurfacesRemove(Surfaces *surf, int idSurf)
{
  int nPoly, nPoint;
  int i, j, k, iPoly, iPoint, pos;
  Surfaces *tmpSurf;
  gboolean *usedPoints;
  int *switchArray;

  g_return_val_if_fail(surf, FALSE);

  pos = isosurfacesGet_surfacePosition(surf, idSurf);
  g_return_val_if_fail(pos >= 0 && pos < surf->nsurf, FALSE);

  if (surf->nsurf == 1)
    return TRUE;

  DBG_fprintf(stderr, "Isosurfaces : remove surface %d from %p.\n", pos, (gpointer)surf);
  /* Simple implementation is to create a new Surfaces object arrays, and to
     copy everything, except the polygons belonging to the given pos. */
  tmpSurf = isosurfacesNew();

  /* Count number of poly and points to remove. */
  usedPoints = g_malloc(sizeof(gboolean) * surf->num_points);
  for (i = 0; i < surf->num_points; i++)
    usedPoints[i] = FALSE;
  nPoly = 0;
  for (i = 0; i < surf->num_polys; i++)
    if (surf->poly_surf_index[i] != pos)
      {
      nPoly += 1;
      for (j = 0; j < surf->poly_num_vertices[i]; j++)
        usedPoints[surf->poly_vertices[i][j]] = TRUE;
      }
  nPoint = 0;
  for (i = 0; i < surf->num_points; i++)
    if (usedPoints[i])
      nPoint += 1;
  DBG_fprintf(stderr, " | remove %d polygons and %d points.\n",
            surf->num_polys - nPoly, surf->num_points - nPoint);

  isosurfacesAllocate(tmpSurf, surf->nsurf - 1, nPoly, nPoint);

  /* Copy from surf to tmpSurf. */
  switchArray = g_malloc(sizeof(int) * surf->num_points);
  iPoint = 0;
  for (i = 0; i < surf->num_points; i++)
    if (usedPoints[i])
      {
      for (k = 0; k < 3; k++)
        {
          tmpSurf->poly_points[iPoint][k] =
            surf->poly_points[i][k];
          tmpSurf->poly_normals[iPoint][k] =
            surf->poly_normals[i][k];
        }
      switchArray[i] = iPoint;
      iPoint += 1;
      if (iPoint > nPoint)
        g_error("Incorrect point checksum.");
      }
  iPoly = 0;
  for (i = 0; i < surf->num_polys; i++)
    {
      if (surf->poly_surf_index[i] != pos)
      {
        if (surf->poly_surf_index[i] > pos)
          tmpSurf->poly_surf_index[iPoly] = surf->poly_surf_index[i] - 1;
        else
          tmpSurf->poly_surf_index[iPoly] = surf->poly_surf_index[i];
        tmpSurf->poly_num_vertices[iPoly] = surf->poly_num_vertices[i];
        tmpSurf->poly_vertices[iPoly] = g_malloc(sizeof(int) *
                                       tmpSurf->poly_num_vertices[iPoly]);
        for (j = 0; j < tmpSurf->poly_num_vertices[iPoly]; j++)
          tmpSurf->poly_vertices[iPoly][j] = switchArray[surf->poly_vertices[i][j]];
        iPoly += 1;
        if (iPoly > nPoly)
          g_error("Incorrect polygon checksum.");
      }
    }
  g_free(usedPoints);
  g_free(switchArray);
  /* Check sum. */
  if (iPoly != nPoly || iPoint != nPoint)
    g_error("Incorrect checksum (%d %d | %d %d).", iPoly, nPoly, iPoint, nPoint);

  /* We replace the arrays between tmpSurf and surf. */
  DBG_fprintf(stderr, " | switch and free arrays.\n");
  g_free(surf->poly_surf_index);
  surf->poly_surf_index = tmpSurf->poly_surf_index;
  tmpSurf->poly_surf_index = (int*)0;

  g_free(surf->poly_num_vertices);
  surf->poly_num_vertices = tmpSurf->poly_num_vertices;
  tmpSurf->poly_num_vertices = (int*)0;

  for (i = 0; i< surf->num_polys; i++)
    g_free(surf->poly_vertices[i]);
  g_free(surf->poly_vertices);
  surf->poly_vertices = tmpSurf->poly_vertices;
  tmpSurf->poly_vertices = (int**)0;

  g_free(surf->poly_points[0]);
  g_free(surf->poly_points);
  surf->poly_points = tmpSurf->poly_points;
  tmpSurf->poly_points = (float**)0;

  g_free(surf->poly_normals[0]);
  g_free(surf->poly_normals);
  surf->poly_normals = tmpSurf->poly_normals;
  tmpSurf->poly_normals = (float**)0;

  isosurfacesFree(tmpSurf);

  /* additionnal tuning. */
  DBG_fprintf(stderr, " | Additional removing.\n");
  surf->num_polys = nPoly;
  surf->num_points = nPoint;
  surf->nsurf -= 1;
  for (i = pos; i < surf->nsurf; i++)
    {
      surf->ids[i] = surf->ids[i + 1];
      surf->resources[i] = surf->resources[i + 1];
    }
  surf->ids = g_realloc(surf->ids, sizeof(int) * surf->nsurf);
  surf->resources = g_realloc(surf->resources,
                        sizeof(SurfaceResource*) * surf->nsurf);
  g_hash_table_foreach(surf->properties, propertiesRemoveSurf, GINT_TO_POINTER(pos));
  
#if DEBUG == 1
  isosurfacesCheck_consistency(surf);
#endif

  return FALSE;
}

gboolean isosurfaces_read_resources(gchar **lines, int nbLines, int position, GString *errorMessage)
{
  SurfaceResource *res;
  gboolean rendered;
  float rgba[4];
  float material[5];
  int k;
  gchar **tokens;

  tokens = g_strsplit(g_strchomp(lines[0]), "\"", 3);
  
  if (!tokens[1] || !tokens[1])
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("Can't parse resource of"
                                     " iso-surfaces on line %d.\n"), position);
      g_strfreev(tokens);
      return FALSE;
    }

  if(sscanf(tokens[2], "%d %f %f %f %f %f %f %f %f %f\n", 
          &rendered, &rgba[0], &rgba[1],
          &rgba[2], &rgba[3], &material[0], &material[1],
          &material[2], &material[3], &material[4]) != 10)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("Can't parse resource of"
                                     " iso-surfaces on line %d.\n"), position);
      g_strfreev(tokens);
      return FALSE;
    }

  res = isosurfacesGet_resourceFromName(tokens[1], (gboolean*)0);
  res->color = colorAdd_floatRGBA(rgba, &k);
  res->rendered = rendered;
  for (k = 0; k < 5; k++)
    res->material[k] = material[k];
  DBG_fprintf(stderr, "Isosurfaces : resources found for surface '%s'\n", tokens[1]);
  g_strfreev(tokens);

  return TRUE;
}

void isosurfaces_export_one_surf_resources(gpointer key, gpointer value, gpointer user_data)
{
  struct foreachFuncExport_struct *str;
  SurfaceResource *res;

  res = (SurfaceResource*)value;
  str = (struct foreachFuncExport_struct*)user_data;
  DBG_fprintf(stderr, "Isosurfaces: exporting surface '%s' properties...", (char *)key);
  g_string_append_printf(str->data, "isosurface_property:\n");
  g_string_append_printf(str->data, "   \"%s\" %d %f %f %f %f %f %f %f %f %f\n",
                   (char *)key, res->rendered, res->color->rgba[0], res->color->rgba[1],
                   res->color->rgba[2], res->color->rgba[3], res->material[0],
                   res->material[1], res->material[2], res->material[3], res->material[4]);
  *(str->nbLinesWritten) += 1;
  DBG_fprintf(stderr, "OK.\n");
}
                   

gboolean isosurfaces_export_resources(GString *data, int *nbLinesWritten,
                              VisuData *dataObj)
{
  int n;
  struct foreachFuncExport_struct str;
 
  if(isosurfaces_resources != NULL)
    {
      n = 0;
      str.nbLinesWritten = &n;
      str.data = data;
      g_hash_table_foreach(isosurfaces_resources, isosurfaces_export_one_surf_resources, &str);

      *nbLinesWritten += 2*n;     
    }
  DBG_fprintf(stderr, "Isosurfaces: exporting OK.\n");
 
  return TRUE;
}

SurfaceResource* isosurfacesGet_resourceFromName(const gchar *surf_name, gboolean *new)
{
  SurfaceResource *res;

  g_return_val_if_fail(surf_name && *surf_name, (SurfaceResource*)0);
  g_return_val_if_fail(isosurfaces_resources, (SurfaceResource*)0);
  
  res = g_hash_table_lookup(isosurfaces_resources, surf_name);
  if(!res)
    {    
      res = g_malloc(sizeof(SurfaceResource));
      isosurfacesInit_resource(res);
      res->surfnom = g_strdup(surf_name);

      DBG_fprintf(stderr, "Isosurfaces : registering new resources for surface '%s'.\n", surf_name);
      
      g_hash_table_insert(isosurfaces_resources, res->surfnom, res);
      if (new)
      *new = TRUE;
    }
  else
    {
      if (new)
      *new = FALSE;
    }
      
  return res;
}
void isosurfacesCopy_resource(SurfaceResource *res, SurfaceResource *res_old)
{
  int i;

  g_return_if_fail(res && res_old);
  
  colorCopy_color(res->color, res_old->color);
  for (i = 0; i < 5; i++)
    res->material[i] = res_old->material[i];
  res->rendered = res_old->rendered;
}

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

  g_return_if_fail(data && surf);

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

  inverted_local_box_matrix[0][0] = 1 / surf->local_box[_DXX];
  inverted_local_box_matrix[0][1] = - surf->local_box[_DYX] /
    surf->local_box[_DXX] / surf->local_box[_DYY];
  inverted_local_box_matrix[0][2] 
    = - ((surf->local_box[_DZX] / surf->local_box[_DXX] -
        surf->local_box[_DYX] * surf->local_box[_DZY] / 
        surf->local_box[_DXX] / surf->local_box[_DYY] ) /
       surf->local_box[_DZZ] );
  inverted_local_box_matrix[1][0] = 0.;
  inverted_local_box_matrix[1][1] = 1 / surf->local_box[_DYY];
  inverted_local_box_matrix[1][2] = - surf->local_box[_DZY] /
    surf->local_box[_DYY] / surf->local_box[_DZZ];
  inverted_local_box_matrix[2][0] = 0.;
  inverted_local_box_matrix[2][1] = 0.;
  inverted_local_box_matrix[2][2] = 1 / surf->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 < surf->num_points; i++)
    {
      for(j=0; j<3; j++)
      {
        old_poly_points[j] = surf->poly_points[i][j];
        old_poly_normals[j] = surf->poly_normals[i][j];
      }
      matrix_productVector(surf->poly_points[i], transform_box_matrix, old_poly_points);
      matrix_productVector(surf->poly_normals[i], transform_box_matrix, old_poly_normals);
    }
}  

Surfaces* isosurfacesNew()
{
  Surfaces *surf;

  surf = g_malloc(sizeof(Surfaces));

  surf->nsurf = 0;
  surf->num_polys = 0;
  surf->num_points = 0;

  surf->poly_surf_index = (int *)0;
  surf->poly_num_vertices = (int *)0;
  surf->poly_vertices = (int **)0;
  surf->poly_points = (float **)0;
  surf->poly_normals = (float **)0;
  surf->ids = (int*)0;
  surf->resources = (SurfaceResource**)0;
  surf->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, freeSurfacesProperties);

  return surf;
}
void isosurfacesFree(Surfaces *surf)
{
  int i;

  g_return_if_fail(surf);

  if (surf->poly_surf_index)
    g_free(surf->poly_surf_index);
  if (surf->poly_num_vertices)
    g_free(surf->poly_num_vertices);
  if (surf->poly_vertices)
    {
      for (i = 0; i< surf->num_polys; i++)
      g_free(surf->poly_vertices[i]);
      g_free(surf->poly_vertices);
    }
  if (surf->poly_points)
    {
      g_free(surf->poly_points[0]);
      g_free(surf->poly_points);
    }
  if (surf->poly_normals)
    {
      g_free(surf->poly_normals[0]);
      g_free(surf->poly_normals);
    }
  if (surf->ids)
    g_free(surf->ids);
  if (surf->resources)
    g_free(surf->resources);
  if (surf->properties)
    g_hash_table_destroy(surf->properties);

  g_free(surf);
}
 
void isosurfacesAllocate(Surfaces *surf, int nsurf, int npolys, int npoints)
{
  int i;

  surf->nsurf      = nsurf;
  surf->num_polys  = npolys;
  surf->num_points = npoints;

  /* for each of the num_polys polygons will contain the surf value
     to which it belongs */
  surf->poly_surf_index = g_malloc(npolys * sizeof(int));
  /* for each of the num_polys polygons will contain the number
     of vertices in it */
  surf->poly_num_vertices = g_malloc(npolys * sizeof(int));
  /* for each of the num_polys polygons will contain the indices
     of vertices in it */   
  surf->poly_vertices = g_malloc(npolys * sizeof(int*));

  /* for each of the num_points,
     poly_points[][0] = x
     poly_points[][1] = y
     poly_points[][2] = z
  */ 
  surf->poly_points = g_malloc(npoints * sizeof(float *));
  surf->poly_points[0] = g_malloc(3 * npoints * sizeof(float));
  for(i = 0; i < npoints; i++)
    surf->poly_points[i] = surf->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
  */  
  surf->poly_normals = g_malloc(npoints * sizeof(float *));
  surf->poly_normals[0] = g_malloc(3 * npoints * sizeof(float));
  for(i = 0; i < npoints; i++)
    surf->poly_normals[i] = surf->poly_normals[0] + i * 3;

  /* Allocating pointers. */
  surf->ids = g_malloc(sizeof(int) * nsurf);
  surf->resources = g_malloc(nsurf * sizeof(SurfaceResource*));
}
void isosurfacesReallocate(Surfaces **surf, int nsurf, int npolys, int npoints)
{
  int i;

  g_return_if_fail(surf);
  
  DBG_fprintf(stderr, "Isosurfaces : reallocate %d %d %d.\n", nsurf, npolys, npoints);
  (*surf)->nsurf      = nsurf;
  (*surf)->num_polys  = npolys;
  (*surf)->num_points = npoints;

  (*surf)->poly_surf_index   = g_realloc((*surf)->poly_surf_index, npolys * sizeof(int));
  (*surf)->poly_num_vertices = g_realloc((*surf)->poly_num_vertices, npolys * sizeof(int));
  (*surf)->poly_vertices     = g_realloc((*surf)->poly_vertices, npolys * sizeof(int*));

  (*surf)->poly_points       = g_realloc((*surf)->poly_points, npoints * sizeof(float *));
  (*surf)->poly_points[0]    = g_realloc((*surf)->poly_points[0], 3 * npoints * sizeof(float));
  for(i = 0; i < npoints; i++)
    (*surf)->poly_points[i] = (*surf)->poly_points[0] + i * 3;

  (*surf)->poly_normals      = g_realloc((*surf)->poly_normals, npoints * sizeof(float *));
  (*surf)->poly_normals[0]   = g_realloc((*surf)->poly_normals[0], 3 * npoints * sizeof(float));
  for(i = 0; i < npoints; i++)
    (*surf)->poly_normals[i] = (*surf)->poly_normals[0] + i * 3;

  (*surf)->ids               = g_realloc((*surf)->ids, sizeof(int) * nsurf);
  (*surf)->resources         = g_realloc((*surf)->resources, nsurf * sizeof(SurfaceResource*));

  /* Dealing with properties reallocation. */
  g_hash_table_foreach((*surf)->properties, propertiesReallocateSurf,
                   GINT_TO_POINTER(nsurf));
}
void isosurfacesInit_resource(SurfaceResource *res)
{
  float rgba[4];
  int position;
  Color *color;

  g_return_if_fail(res);

  rgba[0] = 1.0f;
  rgba[1] = 0.5f;
  rgba[2] = 0.5f;
  rgba[3] = 0.75f;
  color = colorAdd_floatRGBA(rgba, &position);
  res->color = g_malloc(sizeof(Color));
  for (position = 0; position < 4; position++)
    res->color->rgba[position] = color->rgba[position];
  res->material[0] = 0.2f;
  res->material[1] = 1.0f;
  res->material[2] = 0.5f;
  res->material[3] = 0.5f;
  res->material[4] = 0.0f;
  res->rendered = FALSE;
  res->surfnom = (gchar*)0;
}
void hash_free_resource(gpointer res)
{
  isosurfacesFree_resources((SurfaceResource*)res);
}
void isosurfacesFree_resources(SurfaceResource *res)
{
  g_return_if_fail(res);

  g_free(res->color);
}

static void freeSurfacesProperties(gpointer data)
{
  SurfacesProperties *prop;

  prop = (SurfacesProperties*)data;
  g_free(prop->data);
  g_free(prop);
}
static void propertiesRemoveSurf(gpointer key, gpointer value, gpointer data)
{
  int idSurf, i;
  SurfacesProperties *prop;

  idSurf = GPOINTER_TO_INT(data);
  prop = (SurfacesProperties*)value;

  switch (prop->type)
    {
    case G_TYPE_FLOAT:
      for (i = idSurf; i < prop->surf->nsurf; i++)
      ((float*)prop->data)[i] = ((float*)prop->data)[i + 1];
      prop->data = g_realloc(prop->data, prop->surf->nsurf * sizeof(float));
      break;
    default:
      g_warning("Unimplemented format.");
    }
}
static void propertiesReallocateSurf(gpointer key, gpointer value, gpointer data)
{
  int nsurf;
  SurfacesProperties *prop;

  nsurf = GPOINTER_TO_INT(data);
  prop = (SurfacesProperties*)value;

  switch (prop->type)
    {
    case G_TYPE_FLOAT:
      prop->data = g_realloc(prop->data, nsurf * sizeof(float));
      break;
    default:
      g_warning("Unimplemented format.");
    }
}
/* Dealing with properties as floats. */
float* isosurfacesAdd_floatProperty(Surfaces *surf, const gchar* name)
{
  float *data;
  SurfacesProperties *prop;

  g_return_val_if_fail(surf && surf->nsurf > 0, (float*)0);
  g_return_val_if_fail(name && name[0],         (float*)0);

  prop = g_malloc(sizeof(SurfacesProperties));
  prop->type = G_TYPE_FLOAT;
  prop->surf = surf;
  data = g_malloc(sizeof(float) * surf->nsurf);
  prop->data = (gpointer)data;
  g_hash_table_insert(surf->properties, (gpointer)name, (gpointer)prop);
  return data;
}
gboolean isosurfacesAdd_floatPropertyValue(Surfaces *surf, int idSurf,
                                 const gchar* name, float value)
{
  float* data;
  int id;
  SurfacesProperties *prop;

  g_return_val_if_fail(surf, FALSE);
  
  id = isosurfacesGet_surfacePosition(surf, idSurf);
  g_return_val_if_fail(id >= 0 && id < surf->nsurf, FALSE);

  prop = (SurfacesProperties*)g_hash_table_lookup(surf->properties, name);
  if (!prop)
    return FALSE;
  g_return_val_if_fail(prop->surf != surf, FALSE);

  data = (float*)prop->data;
  data[id] = value;
  return TRUE;
}
gboolean isosurfacesGet_floatPropertyValue(Surfaces *surf, int idSurf,
                                 const gchar *name, float *value)
{
  float* data;
  int id;
  SurfacesProperties *prop;

  g_return_val_if_fail(surf && value, FALSE);
  
  id = isosurfacesGet_surfacePosition(surf, idSurf);
  g_return_val_if_fail(id >= 0 && id < surf->nsurf, FALSE);

  prop = (SurfacesProperties*)g_hash_table_lookup(surf->properties, name);
  if (!prop)
    return FALSE;
  g_return_val_if_fail(prop->surf != surf, FALSE);

  data = (float*)prop->data;
  *value = data[id];
  return TRUE;
}
float* isosurfacesGet_floatProperty(Surfaces *surf, const gchar *name)
{
  SurfacesProperties *prop;

  g_return_val_if_fail(surf, (float*)0);

  prop = (SurfacesProperties*)g_hash_table_lookup(surf->properties, name);
  if (prop)
    return (float*)prop->data;
  else
    return (float*)0;
}

gboolean isosurfacesLoad_file(const char *file, Surfaces **surf, GError **error)
{
  GIOChannel* surf_file;
  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, res;
  int sum_polys=0, sum_points=0;
  GIOStatus io_status;
  GString *current_line;
  float *densityData, densityValue;

  g_return_val_if_fail(surf, FALSE);
  g_return_val_if_fail(error, FALSE);

  DBG_fprintf(stderr, "Isosurfaces : trying to load %s file.\n", file);

  *surf = (Surfaces*)0;

  current_line = g_string_new("");

  *error = (GError*)0;
  surf_file = g_io_channel_new_file(file, "r", error);
  if(!surf_file)
    return FALSE;

  /*   DBG_fprintf(stderr, "File opened\n"); */
  *error = (GError*)0;
  io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
  if(io_status != G_IO_STATUS_NORMAL)
    {
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      return FALSE;
    }
  line_number++;  
  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */

  *surf = isosurfacesNew();

  *error = (GError*)0;
  io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
  if(io_status != G_IO_STATUS_NORMAL)
    {
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      isosurfacesFree(*surf);
      *surf = (Surfaces*)0;
      return FALSE;
    }
  line_number++;
  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  if(sscanf(current_line->str, "%lf %lf %lf", &dxx, &dyx, &dyy) != 3)
    {
      *error = g_error_new(VISU_ERROR_ISOSURFACES,
                     VISU_ERROR_FORMAT,
                     _("Line %d doesn't match the [float, float, float]"
                       " pattern."), line_number);
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      isosurfacesFree(*surf);
      *surf = (Surfaces*)0;
      return FALSE;
    }
      
  *error = (GError*)0;
  io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
  if(io_status != G_IO_STATUS_NORMAL)
    {
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      isosurfacesFree(*surf);
      *surf = (Surfaces*)0;
      return FALSE;
    }
  line_number++;
  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  if(sscanf(current_line->str, "%lf %lf %lf", &dzx, &dzy, &dzz) != 3)
    {
      *error = g_error_new(VISU_ERROR_ISOSURFACES,
                     VISU_ERROR_FORMAT,
                     _("Line %d doesn't match the [float, float, float]"
                       " pattern."), line_number);
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      isosurfacesFree(*surf);
      *surf = (Surfaces*)0;
      return FALSE;
    }
      
  *error = (GError*)0;
  io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
  if(io_status != G_IO_STATUS_NORMAL)
    {
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      isosurfacesFree(*surf);
      *surf = (Surfaces*)0;
      return FALSE;
    }
  line_number++;
  /*   DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
  res = sscanf(current_line->str, "%d %d %d", &file_nsurfs, &file_npolys, &file_npoints);
  if(res != 3 || file_nsurfs <= 0 || file_npolys <= 0 || file_npoints <= 0)
    {
      *error = g_error_new(VISU_ERROR_ISOSURFACES,
                     VISU_ERROR_FORMAT,
                     _("Line %d doesn't match the [int > 0, int > 0, int > 0]"
                       " pattern."), line_number);
      g_string_free(current_line, TRUE);
      g_io_channel_unref(surf_file);
      isosurfacesFree(*surf);
      *surf = (Surfaces*)0;
      return FALSE;
    }
  /* From now on, the file is supposed to be a valid surface file. */
  (*surf)->nsurf = file_nsurfs;
  (*surf)->local_box[0] = dxx;
  (*surf)->local_box[1] = dyx;
  (*surf)->local_box[2] = dyy;
  (*surf)->local_box[3] = dzx;
  (*surf)->local_box[4] = dzy;
  (*surf)->local_box[5] = dzz;

  /* Allocate storage arrays. */
  isosurfacesAllocate(*surf, file_nsurfs, file_npolys, file_npoints);

  /* Create a table to store the density values. */
  densityData = isosurfacesAdd_floatProperty(*surf, ISOSURFACES_PROPERTY_POTENTIAL);

  /* For each surf */
  for(i = 0; i < (*surf)->nsurf; i++) 
    {
      int surf_npolys=0, surf_npoints=0;
      
      densityData[i] = 0.;
      (*surf)->ids[i] = i;
      /* Allow some commentaries here begining with a '#' character. */
      do
      {
        /* Get the first line that should contains current surf' name */
        *error = (GError*)0;
        io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
        if(io_status != G_IO_STATUS_NORMAL)
          {
            g_string_free(current_line, TRUE);
            g_io_channel_unref(surf_file);
            isosurfacesFree(*surf);
            *surf = (Surfaces*)0;
            return TRUE;
          }
        line_number++;

        /* If the line begins with a '#', then we try to find a density value. */
        if (current_line->str[0] == '#')
          {
            res = sscanf(current_line->str, ISOSURFACES_FLAG_POTENTIAL" %f", &densityValue);
            if (res == 1)
            densityData[i] = densityValue;
          }
      }
      while (current_line->str[0] == '#');
      DBG_fprintf(stderr, "Line %d read successfully %f\n", line_number, densityData[i]);
      g_strdelimit(current_line->str, "\n", ' ');       
      g_strstrip(current_line->str);
      (*surf)->resources[i] = isosurfacesGet_resourceFromName(current_line->str, (gboolean*)0);

      *error = (GError*)0;
      io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
      if(io_status != G_IO_STATUS_NORMAL)
      {
        g_string_free(current_line, TRUE);
        g_io_channel_unref(surf_file);
        isosurfacesFree(*surf);
        *surf = (Surfaces*)0;
        return TRUE;
      }
      line_number++;
      /*        DBG_fprintf(stderr, "Line %d read successfully\n", line_number); */
      res = sscanf(current_line->str, "%d %d", &surf_npolys, &surf_npoints);
      if(res != 2 || surf_npolys <= 0 || surf_npoints <= 0)
      {
        *error = g_error_new(VISU_ERROR_ISOSURFACES,
                         VISU_ERROR_FORMAT,
                         _("Line %d doesn't match the [int > 0, int > 0]"
                         " pattern."), line_number);
        g_string_free(current_line, TRUE);
        g_io_channel_unref(surf_file);
        isosurfacesFree(*surf);
        *surf = (Surfaces*)0;
        return TRUE;
      }

      sum_polys += surf_npolys;
      if(sum_polys > file_npolys)
      {
        *error = g_error_new(VISU_ERROR_ISOSURFACES,
                         VISU_ERROR_CHECKSUM,
                         _("Error on line %d. Declared number of polygons"
                         " reached."), line_number);
        g_string_free(current_line, TRUE);
        g_io_channel_unref(surf_file);
        isosurfacesFree(*surf);
        *surf = (Surfaces*)0;
        return TRUE;
      }

      sum_points += surf_npoints;
      if(sum_points > file_npoints)
      {
        *error = g_error_new(VISU_ERROR_ISOSURFACES,
                         VISU_ERROR_CHECKSUM,
                         _("Error on line %d. Declared number of points"
                         " reached."), line_number);
        g_string_free(current_line, TRUE);
        g_io_channel_unref(surf_file);
        isosurfacesFree(*surf);
        *surf = (Surfaces*)0;
        return TRUE;
      }

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

        gchar **split_line;
         
        *error = (GError*)0;
        io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
        if(io_status != G_IO_STATUS_NORMAL)
          {
            g_string_free(current_line, TRUE);
            g_io_channel_unref(surf_file);
            isosurfacesFree(*surf);
            *surf = (Surfaces*)0;
            return TRUE;
          }
        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)
                {
                  *error = g_error_new(VISU_ERROR_ISOSURFACES,
                                 VISU_ERROR_FORMAT,
                                 _("Line %dmust begin by an int."),
                                 line_number);
                  g_string_free(current_line, TRUE);
                  g_io_channel_unref(surf_file);
                  isosurfacesFree(*surf);
                  return TRUE;
                }
              (*surf)->poly_num_vertices[npolys_loaded] = nvertex;
              (*surf)->poly_vertices[npolys_loaded] = g_malloc(nvertex * sizeof(double));
              (*surf)->poly_surf_index[npolys_loaded] = i;
              npolys_loaded++;
              continue;
            }
            res = sscanf(split_line[k], "%d", &(*surf)->poly_vertices[npolys_loaded-1][nvertex_i]);
            if(res != 1)
            {
              *error = g_error_new(VISU_ERROR_ISOSURFACES,
                               VISU_ERROR_FORMAT,
                               _("Line %d doesn't match the [int > 3, ...]"
                               " required pattern."), line_number);
              g_string_free(current_line, TRUE);
              g_io_channel_unref(surf_file);
              isosurfacesFree(*surf);
              return TRUE;
            }
            (*surf)->poly_vertices[npolys_loaded-1][nvertex_i] += -1 + npoints_loaded;
            nvertex_i++;
            if(nvertex_i >= nvertex)
            break;
          }

        g_strfreev(split_line);
      }
 
      for(j = 0; j < surf_npoints; j++) 
      {
        *error = (GError*)0;
        io_status = g_io_channel_read_line_string(surf_file, current_line, NULL, error);
        if(io_status != G_IO_STATUS_NORMAL)
          {
            g_string_free(current_line, TRUE);
            g_io_channel_unref(surf_file);
            isosurfacesFree(*surf);
            *surf = (Surfaces*)0;
            return TRUE;
          }
        line_number++;

        if(sscanf(current_line->str, "%f %f %f %f %f %f", 
                &(*surf)->poly_points[npoints_loaded][0],
                &(*surf)->poly_points[npoints_loaded][1],
                &(*surf)->poly_points[npoints_loaded][2],
                &(*surf)->poly_normals[npoints_loaded][0], 
                &(*surf)->poly_normals[npoints_loaded][1], 
                &(*surf)->poly_normals[npoints_loaded][2]) != 6) 
          {
            *error = g_error_new(VISU_ERROR_ISOSURFACES,
                           VISU_ERROR_FORMAT,
                           _("Line %d doesn't match the [float x 6]"
                             " required pattern."), line_number);
            g_string_free(current_line, TRUE);
            g_io_channel_unref(surf_file);
            isosurfacesFree(*surf);
            *surf = (Surfaces*)0;
            return TRUE;            
          }
        npoints_loaded++;
      }
    }

  g_string_free(current_line, TRUE);
  g_io_channel_unref(surf_file);
       
  return TRUE;
}  

void isosurfacesSet_showAll(Surfaces *surf, gboolean show)
{
  int i;

  g_return_if_fail(surf);

  for (i = 0; i < surf->nsurf; i++)
    surf->resources[i]->rendered = show;
}


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(float mat[16], float points[3])
{
  return
    (mat[ 2]*points[0]+
     mat[ 6]*points[1]+
     mat[10]*points[2]+
     mat[14]*1.)/
    (mat[ 3]*points[0]+
     mat[ 7]*points[1]+
     mat[11]*points[2]+
     mat[15]*1.);
}

SurfacesOrder* isosurfacesOrder_new()
{
  SurfacesOrder *order;

  order = g_malloc(sizeof(SurfacesOrder));
  order->allocatedSize = 0;
  order->any_pointer = (int**)0;
  order->any_z = (double*)0;
  order->polygon_number = (int*)0;

  return order;
}
void isosurfacesOrder_free(SurfacesOrder *order)
{
  g_return_if_fail(order);

  if (order->any_pointer)
    g_free(order->any_pointer);
  if (order->any_z)
    g_free(order->any_z);
  if (order->polygon_number)
    g_free(order->polygon_number);

  g_free(order);
}


void isosurfacesOrder_polygons(SurfacesOrder *order, Surfaces *surf[])
{
  int i,j, idSurf, nb;
  float mat[16];

  g_return_if_fail(surf && order);

  DBG_fprintf(stderr, "Isosurfaces : re-ordering polygons in back to front order.\n");
  
  glGetFloatv(GL_MODELVIEW_MATRIX, mat);
  
  /* We compute the number of polygons. */
  nb = 0;
  for( idSurf = 0; surf[idSurf]; idSurf++)
    nb += surf[idSurf]->num_polys;
  DBG_fprintf(stderr, "Isosurfaces : found %d polygons.\n", nb);
  /* If the given order object need to be reallocated, we do it. */
  if (nb > order->allocatedSize)
    {
      DBG_fprintf(stderr, "Isosurfaces : get to reallocate the order object(%d %d).\n",
              order->allocatedSize, nb);
      order->any_z = g_realloc(order->any_z, sizeof(double) * nb);
      order->any_pointer = g_realloc(order->any_pointer, sizeof(int*) * nb);
      order->polygon_number = g_realloc(order->polygon_number, sizeof(int) * nb * 3);
      order->allocatedSize = nb;
    }

  /* For all polygons, we compute the z position of the isobarycentre. */
  DBG_fprintf(stderr, "Isosurfaces : compute z values.\n");
  nb = 0;
  for( idSurf = 0; surf[idSurf]; idSurf++)
    {
      for( i = 0; i < surf[idSurf]->num_polys; i++)
      {
        order->polygon_number[3 * nb] = nb;
        order->polygon_number[3 * nb + 1] = idSurf;
        order->polygon_number[3 * nb + 2] = i;
        order->any_pointer[nb] = &(order->polygon_number[3 * nb]);
        order->any_z[nb] = 0.0;
        for(j = 0; j < surf[idSurf]->poly_num_vertices[i]; j++)
          order->any_z[nb] +=
            z_eye(mat, surf[idSurf]->poly_points[surf[idSurf]->poly_vertices[i][j]]);
        order->any_z[nb] /= surf[idSurf]->poly_num_vertices[i];
        nb += 1;
      }
    }
   
  DBG_fprintf(stderr, "Isosurfaces : sorting...");
  sort_by_z(order->any_pointer, order->any_z, 0, nb - 1);
  DBG_fprintf(stderr, "OK\n");
}


void isosurfacesDraw_surfaces(int OpenGLId, OpenGLView *view,
                        Surfaces *surf[], SurfacesOrder *order)
{
  int i,j, ip, itp, idSurf;
  int nb;
  int itp_old = -1, idSurf_old = -1;
  SurfaceResource *res;
   
  g_return_if_fail(view && surf && order);
   
  DBG_fprintf(stderr, "Isosurfaces : rebuilding surfaces list\n");

  glNewList(OpenGLId, 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);   
    
  /* We compute the number of polygons. */
  nb = 0;
  for( idSurf = 0; surf[idSurf]; idSurf++)
    nb += surf[idSurf]->num_polys;
  DBG_fprintf(stderr, " | found %d polygons.\n", nb);

  /* If order is out of date, we update. */
  if (nb > order->allocatedSize)
    isosurfacesOrder_polygons(order, surf);

  DBG_fprintf(stderr, " | draw polygons.\n");
  for(i = 0; i < nb; i++) {
    idSurf = *(order->any_pointer[i] + 1);
    ip = *(order->any_pointer[i] + 2);
    itp = surf[idSurf]->poly_surf_index[ip];
    /*      if(surf_draw_flag[itp] == 0) continue; */
    if(itp != itp_old || idSurf != idSurf_old)
      {
      res = surf[idSurf]->resources[itp];
      if(res->rendered == FALSE)
        continue;

      /*          glCallList(lists_location + itp); */
      setOpenGlMaterial(res->material, res->color->rgba);
      itp_old = itp;
      idSurf_old = idSurf;
      }
    glBegin(GL_POLYGON);
    for(j = 0; j < surf[idSurf]->poly_num_vertices[ip]; j++ ) {
      glNormal3fv(surf[idSurf]->poly_normals[surf[idSurf]->poly_vertices[ip][j]]);
      glVertex3fv(surf[idSurf]->poly_points[surf[idSurf]->poly_vertices[ip][j]]);
    }
    glEnd();
  }
   

  glPopMatrix();
  glEndList();
}

int isosurfacesGet_nbSurfaces(Surfaces *surf)
{
  if (!surf)
    return -1;

  return surf->nsurf;
}

const gchar* isosurfacesGet_surfaceName(Surfaces *surf, int surf_index)
{
  int id;

  g_return_val_if_fail(surf, (gchar*)0);

  id = isosurfacesGet_surfacePosition(surf, surf_index);
  g_return_val_if_fail(id >= 0 && id <= surf->nsurf, (gchar*)0);

  return surf->resources[id]->surfnom;
}
gboolean isosurfacesGet_surfaceRendered(Surfaces *surf, int surf_index)
{
  int id;

  g_return_val_if_fail(surf, FALSE);

  id = isosurfacesGet_surfacePosition(surf, surf_index);
  g_return_val_if_fail(id >= 0 && id <= surf->nsurf, FALSE);

  return surf->resources[id]->rendered;
}
SurfaceResource* isosurfacesGet_surfaceResource(Surfaces *surf, int surf_index)
{
  int id;

  g_return_val_if_fail(surf, (SurfaceResource*)0);

  id = isosurfacesGet_surfacePosition(surf, surf_index);
  g_return_val_if_fail(id >= 0 && id <= surf->nsurf, (SurfaceResource*)0);

  return surf->resources[id];
}
void isosurfacesSet_surfaceResource(Surfaces *surf, int surf_index, SurfaceResource *res)
{
  int id;

  g_return_if_fail(surf && res);

  id = isosurfacesGet_surfacePosition(surf, surf_index);
  g_return_if_fail(id >= 0 && id <= surf->nsurf);

  surf->resources[id] = res;
}
int isosurfacesGet_surfaceId(Surfaces *surf, int i)
{
  g_return_val_if_fail(i >= 0 && i <= surf->nsurf, -1);
  
  return surf->ids[i];
}
int* isosurfacesGet_surfaceSortedById(Surfaces *surf)
{
  int *ids, i, j, tmp;

  g_return_val_if_fail(surf, (int*)0);

  ids = g_malloc(sizeof(int) * surf->nsurf);
  for (i = 0; i < surf->nsurf; i++)
    ids[i] = surf->ids[i];

  /* Idiotic algorithm to sort all surfaces. */
  for (i = 0; i < surf->nsurf; i++)
    for (j = 0; j < surf->nsurf; j++)
      if (ids[j] > ids[i])
        {
          tmp = ids[i];
          ids[i] = ids[j];
          ids[j] = tmp;
        }
  return ids;
}
int isosurfacesGet_newId(Surfaces *surf)
{
  int i, id;
  
  if (!surf)
    return 0;
  
  id = -1;
  for (i = 0; i < surf->nsurf; i++)
    id = MAX(surf->ids[i], id);
  DBG_fprintf(stderr, "Surfaces : get new id for surfaces %d.\n", id + 1);
  return id + 1;
}

int isosurfacesGet_surfacePosition(Surfaces *surf, int id)
{
  int i;

  g_return_val_if_fail(surf, -1);

  for (i = 0; i < surf->nsurf; i++)
    if (surf->ids[i] == id)
      return i;

  g_warning("Unfound surface with id %d.", id);
  return -1;
}

Generated by  Doxygen 1.6.0   Back to index