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

renderingSpin.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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "renderingSpin.h"
#include "renderingAtomic.h" /* To get the position file format
                        (and posibly in the future, the read
                        method for position) */
#include "renderingAtomic_ascii.h"
#include "renderingAtomic_d3.h"
#include "atomic_xyz.h"
#include <visu_commandLine.h>
#include <visu_configFile.h>
#include <math.h>
#include <assert.h>
#include <coreTools/toolFileFormat.h>
#include <coreTools/toolMatrix.h>
#include <coreTools/toolColor.h>
#include <coreTools/toolConfigFile.h>
#include <coreTools/toolFortran.h>
#include <openGLFunctions/objectList.h>
#include <opengl.h>
#include <extraFunctions/dataNode.h>
#include <renderingBackend/visu_windowInterface.h>

#define FLAG_RESOURCES_SPIN "spin_resources"
#define DESC_RESOURCES_SPIN "Global or element resource for rendering spin module"

#define SPINVALUES_ID     "spinRendering_values"
#define SPINMAXMODULUS_ID "spinRendering_maxModulus"
#define SPIN_THETA   0
#define SPIN_PHI     1
#define SPIN_MODULUS 2

/* An identifier for the different shapes to draw elements. */
enum
  {
    shapeArrow1 = 0,
    shapeArrow2,
    shapeSpinElipsoid,
    nb_of_shapes
  };

/* Parameters for each VisuElement. */
struct spinResources_struct
{
  /* One of this structure is associated to each element. */

  /* Params for the arrow shapes. */
  /* The radius and the length of the hat. */
  float length, height;
  /* The radius and the length of the tail. */
  float u_length, u_height;
  /* The coloring pattern. */
  gboolean use_element_color, use_element_color_hat;

  /* Params for the elipsoid shapes. */
  /* The radius and the length of the hat. */
  float aAxis, bAxis;
  /* The coloring pattern. */
  gboolean elipsoidColor;

  /* The shape used. */
  int shape;

  /* An id of the list associated with the form. */
  int openGLIdentifier;
  /* The associated id for the atomic shape (when used). */
  int openGLIdentifierAtomic;
};
static GType spinElementResourcesTypes[spin_nbElementResources] =
  {G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_FLOAT,
   G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_BOOLEAN, G_TYPE_UINT};
/* Default values. */
#define SPIN_ELEMENT_HAT_RADIUS_DEFAULT  0.8
#define SPIN_ELEMENT_HAT_LENGTH_DEFAULT  2.0
#define SPIN_ELEMENT_TAIL_RADIUS_DEFAULT 0.33
#define SPIN_ELEMENT_TAIL_LENGTH_DEFAULT 0.8
#define SPIN_ELEMENT_HAT_COLOR_DEFAULT   FALSE
#define SPIN_ELEMENT_TAIL_COLOR_DEFAULT  FALSE
#define SPIN_ELEMENT_AAXIS_DEFAULT       2.0
#define SPIN_ELEMENT_BAXIS_DEFAULT       0.8
#define SPIN_ELEMENT_ELIP_COLOR_DEFAULT  FALSE
#define SPIN_ELEMENT_SHAPE_DEFAULT       shapeArrow1

/* Global resources for spin rendering and associated flag. */
static GType spinGlobalResourcesTypes[spin_nbGlobalResources] =
  {G_TYPE_FLOAT, G_TYPE_FLOAT, G_TYPE_FLOAT,
   G_TYPE_UINT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN};
float coneOrientation[2];
float colorWheel;
SpinDrawingPolicy spinPolicy;
gboolean spinAndAtomicRendering;
gboolean spinModulusUsage;

/* Internal variables. */
static DataNode *dataNode;
static GList *allSpinMethods;

/* Names as they appear in the gtk combo box when selecting an element shape. */
/* tab[i] element matches the above enum i-th element. */
const char* shapeNameSpin[nb_of_shapes + 1] = {"Rounded", 
                                     "Edged", 
                                     "Elipsoid",
                                     (const char*)0};
const char** shapeNameSpin_UTF8;

const char* policyNameSpin[policyNbModes + 1] = {"always", 
                                     "never", 
                                     "atomic",
                                     (const char*)0};
const char** policyNameSpin_UTF8;


/* The OpenGL identifier to store the glObjectLists that
   describe the atoms. */
int identifierSpheresSpin;

/* Local methods. */
static gboolean loadSpin(VisuData *data, FileFormat *format, GError **error);
gboolean readSpinResources(gchar **lines, int nbLines,
                     int position, GString *errorMessage);
gboolean exportResourcesRenderingSpin(GString *data, int *nbLinesWritten,
                              VisuData *dataObj);
void setVariablesForSpinMethod(GObject *visu, gpointer data);
static struct spinResources_struct* getSpinResources(VisuElement *ele);
static void onSpinParametersChanged(VisuData *dataObj, VisuNode *node, gpointer data);

/* Local loading methods. */
static RenderingFormatLoad* spinAsciiInit();
static RenderingFormatLoad* spinBinaryInit();
static gboolean read_spin_file(VisuData *data, const char* fileName,
                         FileFormat *format, GError **error);
static gboolean read_binary_file(VisuData *data, const char* fileName,
                         FileFormat *format, GError **error);


int rspin_get_number_of_shapes()
{
  return nb_of_shapes;
}

int rspin_shape_name_to_number(const char *name)
{
  int i=0;
  if(name == NULL) 
    return -1;

  for(i=0; i<nb_of_shapes; i++)
    if(strcmp(name, shapeNameSpin[i]) == 0)
      return i;

  return -1;
}

const char* rspin_shape_number_to_name(int n)
{
  if(n>=nb_of_shapes && n < 0)
    return NULL;
  
  return shapeNameSpin[n];
}
const char* rspin_shape_number_to_translated_name(int n)
{
  if(n>=nb_of_shapes && n < 0)
    return NULL;
  
  return shapeNameSpin_UTF8[n];
}



int rspin_hiding_name_to_number(const char *name)
{
  int i=0;
  if(name == NULL) 
    return -1;

  for(i=0; i<policyNbModes; i++)
    if(strcmp(name, policyNameSpin[i]) == 0)
      return i;

  return -1;
}

const char* rspin_hiding_number_to_name(int n)
{
  if(n>=policyNbModes && n < 0)
    return NULL;
  
  return policyNameSpin[n];
}
const char* rspin_hiding_number_to_translated_name(int n)
{
  if(n>=policyNbModes && n < 0)
    return NULL;
  
  return policyNameSpin_UTF8[n];
}

float returnOneF()
{
  return 1.0;
}

/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/
/* This function is responsible for binding the module with the core. A module NEED */
/* a function of this kind, and it has to be added in the externalRenderingMethods.h file */
/* for the program to know it exists. */ 
RenderingMethod* initSpin()
{
  RenderingMethod *spin = NULL;
  /* Name & desc that appear when selecting the "input method" in the config tab. */
  char *methodName = _("Spin visualisation");
  char *methodDescr = _("It draws arrows at given positions to represent an atom "
                  "and its spin.");
  RenderingFormatLoad *meth;
  GList *tmpLst;

  GList *formatListPos = NULL;
  GList *formatListSpin = NULL;

  /* A pointer to store the location of the icon as it is shown in the config menu. */
  gchar *iconPath;

  /* The names & descs of the resources the module supports. */
  /* A resource is something that can be modified according to user prefs. */
  /* For example : drawing atoms as cubes instead of drawing them as spheres. */
  VisuConfigFileEntry *resourceEntry;


  DBG_fprintf(stderr,"Initialising the spin rendering method...\n");

  /* We check that the atomic rendering has been already defined, to use its own
     loader and file formats. */
  if (!pointerOnRenderingAtomicMethod)
    g_error("Can't initialize the RenderingSpin method,"
            " renderingAtomic must be initialized first. Aborting...\n");
  formatListPos = renderingMethodGet_fileType(pointerOnRenderingAtomicMethod, FILE_KIND_POSITION);

  /* We create the list of spin file formats. */
  formatListSpin = (GList*)0;
  allSpinMethods = (GList*)0;
  meth = spinAsciiInit();
  if (meth)
    allSpinMethods = g_list_prepend(allSpinMethods, meth);
  meth = spinBinaryInit();
  if (meth)
    allSpinMethods = g_list_prepend(allSpinMethods, meth);
  allSpinMethods = g_list_sort(allSpinMethods, renderingMethodCompare_priority);
  tmpLst = allSpinMethods;
  while (tmpLst)
    {
      formatListSpin = g_list_append(formatListSpin, ((RenderingFormatLoad*)tmpLst->data)->fmt);
      tmpLst = g_list_next(tmpLst);
    }
  
  /* Calling the constructor to create a new renderingMethod. */
  spin = renderingMethod_new("Spin visualisation", methodName, methodDescr, 2, loadSpin);
  renderingMethodSet_fileType(spin, formatListPos, FILE_KIND_POSITION, _("Position files"));
  renderingMethodSet_fileType(spin, formatListSpin, FILE_KIND_SPIN, _("Spin files"));

  /* Setting up the icon. */
  iconPath = g_build_filename(v_sim_pixmaps_dir, "stock_spin.png", NULL);
  renderingMethodSet_icon(spin, iconPath);
  g_free(iconPath);

  /* Binding this new method with OpenGL drawing funcs. */
  setOpenGLMethods(spin, rspin_createShapeSpin, rspin_placeNodeSpin, returnOneF);

  /* Ok now it's time to create and register this module as a new one using the variables
     we initialised above. */
  resourceEntry = visuConfigFileAdd_entry(VISU_CONFIGFILE_RESOURCE,
                                FLAG_RESOURCES_SPIN,
                                DESC_RESOURCES_SPIN,
                                1, readSpinResources);
  visuConfigFileAdd_exportFunction(VISU_CONFIGFILE_RESOURCE,
                           exportResourcesRenderingSpin);
  

  shapeNameSpin_UTF8 = g_malloc(sizeof(gchar*) * nb_of_shapes);
  shapeNameSpin_UTF8[0] = _("Rounded arrow");
  shapeNameSpin_UTF8[1] = _("Edged arrow");
  shapeNameSpin_UTF8[2] = _("Elipsoid");


  /* Initialise the OpenGl part by reserving space in the display list to draw objects. */
  identifierSpheresSpin = openGLObjectList_new(NMAX_TP);
  spinPolicy = commandLineGet_spinHidingMode();
  spinAndAtomicRendering = commandLineGet_spinAndAtomic();
  spinModulusUsage = FALSE;
  coneOrientation[0] = 0.;
  coneOrientation[1] = 0.;
  colorWheel = 0.;

  /* We set a general pointer to retrieve this method later. */
  pointerOnRenderingSpinMethod = spin;

  /* Connect to the signal method changed to set or unset some variables
     when spin is current or not. */
  g_signal_connect(G_OBJECT(visu), "renderingChanged",
               G_CALLBACK(setVariablesForSpinMethod), (gpointer)spin);

  /* Register a new NodeData. */
  dataNode = nodeDataNew(SPINVALUES_ID, G_TYPE_FLOAT);
  nodeDataSet_label(dataNode, _("Spin (\316\270, \317\206, mod.)"));
  nodeDataSet_callback(dataNode, onSpinParametersChanged, (gpointer)0);

  return spin;
}

static RenderingFormatLoad* spinAsciiInit()
{
  /* The file types this module support and a description for each of these. */
  char *typeSpin[] = {"*.spin", "*.sp", NULL};
  char *descrSpin = _("Ascii spin files");
  RenderingFormatLoad *meth;
  
  meth = g_malloc(sizeof(RenderingFormatLoad));
  meth->name = "Plain text native spin format of V_Sim.";
  meth->fmt = fileFormatNew(descrSpin, typeSpin);
  if (!meth->fmt)
    g_error("Can't initialize the rendering spin method, aborting...\n");
  meth->priority = 50;
  meth->load = read_spin_file;

  return meth;
}

static RenderingFormatLoad* spinBinaryInit()
{
  /* The file types this module support and a description for each of these. */
  char *typeSpin[] = {"*.bspin", "*.bsp", NULL};
  char *descrSpin = _("Binary spin files");
  RenderingFormatLoad *meth;
  
  meth = g_malloc(sizeof(RenderingFormatLoad));
  meth->name = "Binary native spin format of V_Sim.";
  meth->fmt = fileFormatNew(descrSpin, typeSpin);
  if (!meth->fmt)
    g_error("Can't initialize the rendering spin method, aborting...\n");
  meth->priority = 10;
  meth->load = read_binary_file;

  return meth;
}

void setVariablesForSpinMethod(GObject *visu, gpointer data)
{
  if (getRenderingMethodInUse() == (RenderingMethod*)data)
    visuElementSet_updateNodesOnMaterialChange();
  else
    visuElementUnset_updateNodesOnMaterialChange();
}


/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/
/* The following are the methods responsible of dealing with the reading of files. */
/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/

/* This is the public method to load a spin file.
   The VisuData should be already allocated and nodes should exist. */
gboolean rspin_load(VisuData *data, FileFormat *format, GError **error)
{
  gchar *file;
  gboolean loadOk;
  GList *tmpLst;
  FileFormat *fmt;

  g_return_val_if_fail(error && *error == (GError*)0, FALSE);

  if (!data)
    return 0;

  file = visuDataGet_file(data, FILE_KIND_SPIN, &fmt);
  if (!file)
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FILE,
                     _("No file name available."));
      return FALSE;
    }
  
  if (g_file_test(file, G_FILE_TEST_IS_DIR))
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FILE,
                     _("WARNING! The specified file is"
                       " a directory indeed. Can't load"
                       " a directory!\n"));
      return FALSE;
    }
  
  loadOk = FALSE;
  tmpLst = allSpinMethods;
  while (tmpLst && !loadOk)
    {
      /* Each load may set error even if the format is not recognise
       and loadOK is FALSE, then we need to free the error. */
      if (*error)
      g_error_free(*error);
      *error = (GError*)0;
      if (!fmt || ((RenderingFormatLoad*)tmpLst->data)->fmt == fmt)
      {
        DBG_fprintf(stderr,"Rendering Spin : testing '%s' with format : %s.\n",
                  file, ((RenderingFormatLoad*)tmpLst->data)->name);
        if (((RenderingFormatLoad*)tmpLst->data)->load)
          loadOk = ((RenderingFormatLoad*)tmpLst->data)->load
            (data, file, ((RenderingFormatLoad*)tmpLst->data)->fmt, error);
        else
          loadOk = FALSE;
      }
      tmpLst = g_list_next(tmpLst);
    }

  if (!loadOk)
    {
      if (!*error)
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FILE,
                       _("WARNING : impossible to load this file.\n"));
      return FALSE;
    }

  return TRUE;
}

/* This is the method associated to the reading of supported spin files. */
static gboolean read_spin_file(VisuData *data, const char* fileName,
                         FileFormat *format, GError **error)
{
  char line[MAX_LINE_LENGTH] = "\0";
  float theta=0, phi=0, module = 0;
  float *svgSpinValues, *svgMaxSpinModulus;
  int i=0, itrash = 0, iele;
  VisuNode *currentNode = NULL;
  FILE *readFrom;

  g_return_val_if_fail(error && *error == (GError*)0, FALSE);

  readFrom = fopen(fileName, "r");
  if (!readFrom)
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FILE,
                     _("WARNING : impossible to open this spin file.\n"));
      return FALSE;
    }

  /* The first line is a commentry. */
  fgets(line, MAX_LINE_LENGTH, readFrom);
  if(feof(readFrom))
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FORMAT,
                     _("WARNING : spin file should have one line at least.\n"));
      fclose(readFrom);
      return FALSE;
    }
   
  /* Create a storage for max values of spin modulus for each element. */
  svgMaxSpinModulus = g_malloc(sizeof(float) * data->ntype);
  visuDataSet_property(data, SPINMAXMODULUS_ID, (gpointer)svgMaxSpinModulus);
  visuDataAdd_nodeProperty(data, SPINVALUES_ID, freeFloat);
  nodeDataSet_used(dataNode, data, 3);
  for(i=1;i<=data->nbOfAllStoredNodes;i++)
    {
      fgets(line, MAX_LINE_LENGTH, readFrom);
      if(feof(readFrom)) break;

      currentNode = visuDataGet_nodeFromNumber(data, i);
      if(currentNode == 0) 
      {
        g_warning("Information for node number %d can't be retrieved.", i);
        continue;
      }
      
      if(sscanf(line, "%d %f %f %f", &itrash, &module, &theta, &phi) != 4)
      {
        g_warning("line number #%d is invalid."
                " Setting node parameters to default ones...", i);
        theta = 0.;
        phi = 0.;
        module = 0.;
      }      
      svgSpinValues = g_malloc(sizeof(float) * 3);
      svgSpinValues[SPIN_THETA] = theta;
      svgSpinValues[SPIN_PHI] = phi;
      svgSpinValues[SPIN_MODULUS] = module;
      visuDataSet_nodeProperty(data, currentNode, SPINVALUES_ID,
                         (gpointer)svgSpinValues);
      iele = currentNode->posElement;
      svgMaxSpinModulus[iele] = (module > svgMaxSpinModulus[iele])?module:svgMaxSpinModulus[iele];
    }
  fclose(readFrom);
  itrash = i;
  for(i = itrash; i <= data->nbOfAllStoredNodes; i++)
    {
      currentNode = visuDataGet_nodeFromNumber(data, i);
      svgSpinValues = g_malloc(sizeof(float) * 3);
      svgSpinValues[SPIN_THETA] = 0.;
      svgSpinValues[SPIN_PHI] = 0.;
      svgSpinValues[SPIN_MODULUS] = 0.;
      visuDataSet_nodeProperty(data, currentNode, SPINVALUES_ID,
                         (gpointer)svgSpinValues);
    }
  return TRUE;
}

/* This is the method associated to the reading of binary spin files. */
static gboolean read_binary_file(VisuData *data, const char* fileName,
                         FileFormat *format, GError **error)
{
  FILE *readFrom;
  gboolean valid;
  EndianId endian;
  unsigned int nspins;
  double *spins;
  int i, iele;
  float *svgSpinValues, *svgMaxSpinModulus;
  VisuNode *currentNode;

  g_return_val_if_fail(error && *error == (GError*)0, FALSE);

  readFrom = fopen(fileName, "r");
  if (!readFrom)
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FILE,
                     _("WARNING : impossible to open this spin file.\n"));
      return FALSE;
    }

  /* Try to find the endianness. */
  valid = toolFortranTest_endianness(4, readFrom, error, &endian);
  if (!valid)
    {
      fclose(readFrom);
      return FALSE;
    }

  /* Try to the number of spins. */
  valid = toolFortranRead_integer(&nspins, 1, readFrom, error, endian, TRUE);
  if (!valid)
    {
      fclose(readFrom);
      return FALSE;
    }

  /* From now on, we consider to a have valid spin file. */
  if ((int)nspins != data->nbOfAllStoredNodes)
    {
      *error = g_error_new(VISU_ERROR_RENDERING, RENDERING_ERROR_FORMAT,
                     _("WARNING : number of spin differs from number of nodes.\n"));
      fclose(readFrom);
      return TRUE;
    }
  
  spins = g_malloc(sizeof(double) * 3 * nspins);
  /* Read module. */
  valid = toolFortranRead_double(spins, nspins, readFrom, error, endian, TRUE);
  if (!valid)
    {
      g_free(spins);
      fclose(readFrom);
      return TRUE;
    }
  /* Read theta. */
  valid = toolFortranRead_double(spins + nspins, nspins, readFrom, error, endian, TRUE);
  if (!valid)
    {
      g_free(spins);
      fclose(readFrom);
      return TRUE;
    }
  /* Read phi. */
  valid = toolFortranRead_double(spins + 2 * nspins, nspins, readFrom, error, endian, TRUE);
  if (!valid)
    {
      g_free(spins);
      fclose(readFrom);
      return TRUE;
    }
  /* Close the file. */
  fclose(readFrom);

  /* Create a storage for max values of spin modulus for each element. */
  svgMaxSpinModulus = g_malloc(sizeof(float) * data->ntype);
  visuDataSet_property(data, SPINMAXMODULUS_ID, (gpointer)svgMaxSpinModulus);
  visuDataAdd_nodeProperty(data, SPINVALUES_ID, freeFloat);
  nodeDataSet_used(dataNode, data, 3);
  for(i = 0; i < data->nbOfAllStoredNodes; i++)
    {
      currentNode = visuDataGet_nodeFromNumber(data, i + 1);
      if(currentNode == 0) 
      {
        g_warning("Information for node number %d can't be retrieved.", i);
        continue;
      }
      
      svgSpinValues = g_malloc(sizeof(float) * 3);
      svgSpinValues[SPIN_MODULUS] = (float)spins[i];
      svgSpinValues[SPIN_THETA]   = (float)spins[nspins + i];
      svgSpinValues[SPIN_PHI]     = (float)spins[2 * nspins + i];
      visuDataSet_nodeProperty(data, currentNode, SPINVALUES_ID,
                         (gpointer)svgSpinValues);
      iele = currentNode->posElement;
      svgMaxSpinModulus[iele] = MAX((float)spins[i], svgMaxSpinModulus[iele]);
    }

  g_free(spins);
  return TRUE;
}

void rspin_addLoadMethod(RenderingFormatLoad* meth)
{
  g_return_if_fail(meth && meth->load);

  DBG_fprintf(stderr, "Rendering Spin : adding a new loading method '%s'.\n", meth->name);
  allSpinMethods = g_list_prepend(allSpinMethods, meth);
  allSpinMethods = g_list_sort(allSpinMethods, renderingMethodCompare_priority);
  if (meth->fmt)
    renderingMethodAdd_fileFormat(pointerOnRenderingSpinMethod, meth->fmt, 0);
}

static gboolean loadSpin(VisuData *data, FileFormat *format, GError **error)
{
  g_return_val_if_fail(error && *error == (GError*)0, FALSE);

  if (!data)
    return 0;
  
  DBG_fprintf(stderr, "Rendering Spin : starting loadSpin procedure...\n");

  if(!renderingAtomicLoad(data, format, error))
    return FALSE;
  /* If we have errors, we return. */
  if (*error)
    return TRUE;

  if (!rspin_load(data, format, error))
    return FALSE;
  /* If we have errors, we return. */
  if (*error)
    return TRUE;

  DBG_fprintf(stderr, "loading OK.\n");
  return TRUE;
}


/*******************************/
/* Access to global resources. */
/*******************************/
gpointer rspin_getGlobalResource(SpinGlobalResources property, GType *type)
{
  g_return_val_if_fail(property < spin_nbGlobalResources, (gpointer)0);
  g_return_val_if_fail(type, (gpointer)0);

  *type = spinGlobalResourcesTypes[property];
  switch (property)
    {
    case spin_globalConeTheta:
      return coneOrientation;
    case spin_globalConePhi:
      return coneOrientation + 1;
    case spin_globalColorWheel:
      return &colorWheel;
    case spin_globalHidingMode:
      return &spinPolicy;
    case spin_globalAtomic:
      return &spinAndAtomicRendering;
    case spin_globalModulus:
      return &spinModulusUsage;
    default:
      g_error("Wrong implementation, property value should be handled by the switch.");
    }
  return (gpointer)0;
}

gboolean rspin_setGlobalResource_boolean(SpinGlobalResources property,
                               gboolean value)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(property < spin_nbGlobalResources, FALSE);

  data = rspin_getGlobalResource(property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_BOOLEAN, FALSE);
  
  if (*(gboolean*)data == value)
    return FALSE;
  
  *(gboolean*)data = value;
  return TRUE;
}
gboolean rspin_setGlobalResource_uint(SpinGlobalResources property,
                              guint value)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(property < spin_nbGlobalResources, FALSE);

  data = rspin_getGlobalResource(property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_UINT, FALSE);
  
  if (*(guint*)data == value)
    return FALSE;
  
  *(guint*)data = value;
  return TRUE;
}
gboolean rspin_setGlobalResource_float(SpinGlobalResources property,
                               gfloat value)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(property < spin_nbGlobalResources, FALSE);

  data = rspin_getGlobalResource(property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_FLOAT, FALSE);
  
  if (*(gfloat*)data == value)
    return FALSE;
  
  *(gfloat*)data = value;
  return TRUE;
}
gboolean rspin_getGlobalResource_boolean(SpinGlobalResources property)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(property < spin_nbGlobalResources, FALSE);

  data = rspin_getGlobalResource(property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_BOOLEAN, FALSE);
  
  return *(gboolean*)data;
}
guint rspin_getGlobalResource_uint(SpinGlobalResources property)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(property < spin_nbGlobalResources, FALSE);

  data = rspin_getGlobalResource(property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_UINT, FALSE);
  
  return *(guint*)data;
}
gfloat rspin_getGlobalResource_float(SpinGlobalResources property)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(property < spin_nbGlobalResources, FALSE);

  data = rspin_getGlobalResource(property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_FLOAT, FALSE);
  
  return *(gfloat*)data;
}


/********************************/
/* Access to element resources. */
/********************************/
static struct spinResources_struct* getSpinResources(VisuElement *ele)
{
  struct spinResources_struct *str;
  
  g_return_val_if_fail(ele, (struct spinResources_struct*)0);

  str = (struct spinResources_struct *)visuElementGet_property(ele, "spinElementResources");
  if(!str)
    {
      str = g_malloc(sizeof(struct spinResources_struct));

      str->shape                 = SPIN_ELEMENT_SHAPE_DEFAULT;
      str->length                = SPIN_ELEMENT_HAT_RADIUS_DEFAULT;
      str->u_length              = SPIN_ELEMENT_TAIL_RADIUS_DEFAULT;
      str->height                = SPIN_ELEMENT_HAT_LENGTH_DEFAULT;
      str->u_height              = SPIN_ELEMENT_TAIL_LENGTH_DEFAULT;
      str->use_element_color     = SPIN_ELEMENT_TAIL_COLOR_DEFAULT;
      str->use_element_color_hat = SPIN_ELEMENT_HAT_COLOR_DEFAULT;
      str->aAxis                 = SPIN_ELEMENT_AAXIS_DEFAULT;
      str->bAxis                 = SPIN_ELEMENT_BAXIS_DEFAULT;
      str->elipsoidColor         = SPIN_ELEMENT_ELIP_COLOR_DEFAULT;
      str->openGLIdentifier = openGLObjectList_new(1);
      str->openGLIdentifierAtomic = -1;

      visuElementSet_property(ele, "spinElementResources", (gpointer)str);
    }
  return str;
}
gpointer rspin_getElementResource(VisuElement *ele, SpinElementResources property, GType *type)
{
  struct spinResources_struct *str;

  g_return_val_if_fail(property < spin_nbElementResources, (gpointer)0);
  g_return_val_if_fail(type, (gpointer)0);
  
  str = getSpinResources(ele);

  *type = spinElementResourcesTypes[property];
  switch (property)
    {
    case spin_elementHatLength:
      return &str->length;
    case spin_elementTailLength:
      return &str->u_length;
    case spin_elementHatRadius:
      return &str->height;
    case spin_elementTailRadius:
      return &str->u_height;
    case spin_elementHatColor:
      return &str->use_element_color_hat;
    case spin_elementTailColor:
      return &str->use_element_color;
    case spin_elementShape:
      return &str->shape;
    case spin_elementAAxis:
      return &str->aAxis;
    case spin_elementBAxis:
      return &str->bAxis;
    case spin_elementElipsoidColor:
      return &str->elipsoidColor;
    default:
      g_error("Wrong implementation, property value should be handled by the switch.");
    }
  return (gpointer)0;
}
gboolean rspin_setElementResource_boolean(VisuElement *ele, SpinElementResources property,
                                gboolean value)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(ele && property < spin_nbElementResources, FALSE);

  data = rspin_getElementResource(ele, property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_BOOLEAN, FALSE);
  
  if (*(gboolean*)data == value)
    return FALSE;
  
  *(gboolean*)data = value;
  return TRUE;
}
gboolean rspin_setElementResource_uint(VisuElement *ele, SpinElementResources property,
                               guint value)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(ele && property < spin_nbElementResources, FALSE);

  data = rspin_getElementResource(ele, property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_UINT, FALSE);
  
  if (*(guint*)data == value)
    return FALSE;
  
  *(guint*)data = value;
  return TRUE;
}
gboolean rspin_setElementResource_float(VisuElement *ele, SpinElementResources property,
                              gfloat value)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(ele && property < spin_nbElementResources, FALSE);

  data = rspin_getElementResource(ele, property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_FLOAT, FALSE);
  
  if (*(gfloat*)data == value)
    return FALSE;
  
  *(gfloat*)data = value;
  return TRUE;
}
gboolean rspin_getElementResource_boolean(VisuElement *ele, SpinElementResources property)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(ele && property < spin_nbElementResources, FALSE);

  data = rspin_getElementResource(ele, property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_BOOLEAN, FALSE);
  
  return *(gboolean*)data;
}
guint rspin_getElementResource_uint(VisuElement *ele, SpinElementResources property)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(ele && property < spin_nbElementResources, FALSE);

  data = rspin_getElementResource(ele, property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_UINT, FALSE);
  
  return *(guint*)data;
}
gfloat rspin_getElementResource_float(VisuElement *ele, SpinElementResources property)
{
  GType type;
  gpointer data;

  g_return_val_if_fail(ele && property < spin_nbElementResources, FALSE);

  data = rspin_getElementResource(ele, property, &type);
  g_return_val_if_fail(data, FALSE);
  g_return_val_if_fail(type == G_TYPE_FLOAT, FALSE);
  
  return *(gfloat*)data;
}


/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/
/* Ok now we introduce the functions used to load/save resources of our module. */
/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/

#define FLAG_ELEMENT_ARROW "spin_element_arrow_params"
static gboolean readElementArrow(gchar **lines, int nbLines,
                         int position, VisuData *dataObj, GError **error)
{
  float size[4];
  gboolean color[2];
  gboolean res;
  VisuElement *ele;
  struct spinResources_struct *str;
  gchar **tokens;
  int id;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  tokens = g_strsplit_set(lines[0], " \n", MAX_LINE_LENGTH);
  id = 0;
  /* Read the element. */
  res = configFileRead_elementFromTokens(tokens, &id, &ele, 1, position, error);
  if (!res)
    {
      g_strfreev(tokens);
      return FALSE;
    }
  /* Read the size params : 4 floats. */
  res = configFileRead_floatFromTokens(tokens, &id, size, 4, position, error);
  if (!res)
    {
      g_strfreev(tokens);
      return FALSE;
    }
  /* Read the color params : 2 booleans. */
  res = configFileRead_booleanFromTokens(tokens, &id, color, 2, position, error);
  if (!res)
    {
      g_strfreev(tokens);
      return FALSE;
    }
  g_strfreev(tokens);

  /* All is OK, we store the values. */
  str = getSpinResources(ele);
  str->height                = size[0];
  str->u_height              = size[1];
  str->length                = size[2];
  str->u_length              = size[3];
  str->use_element_color     = color[0];
  str->use_element_color_hat = color[1];
  if (dataObj)
    rspin_createShapeSpin(dataObj, ele);

  return TRUE;
}
#define FLAG_ELEMENT_ELIPSOID "spin_element_elipsoid_params"
static gboolean readElementElipsoid(gchar **lines, int nbLines,
                            int position, VisuData *dataObj, GError **error)
{
  float size[2];
  gboolean color[1];
  gboolean res;
  VisuElement *ele;
  struct spinResources_struct *str;
  gchar **tokens;
  int id;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  tokens = g_strsplit_set(lines[0], " \n", MAX_LINE_LENGTH);
  id = 0;
  /* Read the element. */
  res = configFileRead_elementFromTokens(tokens, &id, &ele, 1, position, error);
  if (!res)
    {
      g_strfreev(tokens);
      return FALSE;
    }
  /* Read the size params : 2 floats. */
  res = configFileRead_floatFromTokens(tokens, &id, size, 2, position, error);
  if (!res)
    {
      g_strfreev(tokens);
      return FALSE;
    }
  /* Read the color params : 1 boolean. */
  res = configFileRead_booleanFromTokens(tokens, &id, color, 1, position, error);
  if (!res)
    {
      g_strfreev(tokens);
      return FALSE;
    }
  g_strfreev(tokens);

  /* All is OK, we store the values. */
  str = getSpinResources(ele);
  str->aAxis         = size[0];
  str->bAxis         = size[2];
  str->elipsoidColor = color[1];
  if (dataObj)
    rspin_createShapeSpin(dataObj, ele);

  return TRUE;
}
#define FLAG_ELEMENT_SHAPE "spin_element_shape"
static gboolean readElementShape(gchar **lines, int nbLines,
                         int position, VisuData *dataObj, GError **error)
{
  gchar **shapes;
  int shapeId;
  gboolean res;
  VisuElement *ele;
  struct spinResources_struct *str;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  /* Read a string.*/
  res = configFileRead_stringWithElement(lines[0], position, &shapes, 1, &ele, error);
  if (*error)
    return FALSE;
  if (res)
    {
      /* All is OK, we store the values. */
      shapeId = rspin_shape_name_to_number(shapes[0]);
      if (shapeId == -1)
      {
        *error = g_error_new(CONFIG_FILE_ERROR, CONFIG_FILE_ERROR_READ,
                         _("WARNING! Parse error at line %d," 
                         " the shape '%s' is unknown.\n"), 
                         position, shapes[0]);
        g_strfreev(shapes);
        return FALSE;
      }
      g_strfreev(shapes);
      str = getSpinResources(ele);
      str->shape = shapeId;
      if (dataObj)
      rspin_createShapeSpin(dataObj, ele);
    }
  return res;
}

#define FLAG_SPIN_CONE_ANGLE "spin_global_color_cone"
static gboolean readSpinColorCone(gchar **lines, int nbLines,
                           int position, VisuData *dataObj, GError **error)
{
  float angles[2];
  gboolean res;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  /* Read one floating point values.*/
  res = configFileRead_float(lines[0], position, angles, 2, error);
  if (*error)
    return FALSE;
  if (res)
    {
      /* All is OK, we store the values. */
      coneOrientation[0] = angles[0];
      coneOrientation[1] = angles[1];
    }
  return res;
}
#define FLAG_SPIN_WHEEL_ANGLE "spin_global_color_wheel"
static gboolean readSpinColorWheel(gchar **lines, int nbLines,
                           int position, VisuData *dataObj, GError **error)
{
  float angle;
  gboolean res;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  /* Read one floating point values.*/
  res = configFileRead_float(lines[0], position, &angle, 1, error);
  if (*error)
    return FALSE;
  if (res)
    /* All is OK, we store the values. */
    colorWheel = angle;
  return res;
}
#define FLAG_SPIN_HIDING_MODE "spin_global_hiding_mode"
static gboolean readSpinHidingMode(gchar **lines, int nbLines,
                           int position, VisuData *dataObj, GError **error)
{
  gchar **mode;
  int modeId;
  gboolean res;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  /* Read a string.*/
  res = configFileRead_string(lines[0], position, &mode, 1, error);
  if (*error)
    return FALSE;
  if (res)
    {
      /* All is OK, we store the values. */
      modeId = rspin_hiding_name_to_number(g_strstrip(mode[0]));
      if (modeId == -1)
      {
        *error = g_error_new(CONFIG_FILE_ERROR, CONFIG_FILE_ERROR_READ,
                         _("WARNING! Parse error at line %d," 
                         " the hiding mode '%s' is unknown.\n"), 
                         position, mode[0]);
        g_strfreev(mode);
        return FALSE;
      }
      g_strfreev(mode);
      spinPolicy = modeId;
    }
  return res;
}
#define FLAG_SPIN_AND_ATOMIC "spin_global_atomic"
static gboolean readSpinAndAtomic(gchar **lines, int nbLines,
                          int position, VisuData *dataObj, GError **error)
{
  gboolean use;
  gboolean res;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  /* Read one floating point values.*/
  res = configFileRead_boolean(lines[0], position, &use, 1, error);
  if (*error)
    return FALSE;
  if (res)
    /* All is OK, we store the values. */
    spinAndAtomicRendering = use;
  return res;
}
#define FLAG_SPIN_MODULUS "spin_global_modulus"
static gboolean readSpinModulus(gchar **lines, int nbLines,
                           int position, VisuData *dataObj, GError **error)
{
  gboolean use;
  gboolean res;

  g_return_val_if_fail(error && (*error == (GError*)0), FALSE);

  /* Read one floating point values.*/
  res = configFileRead_boolean(lines[0], position, &use, 1, error);
  if (*error)
    return FALSE;
  if (res)
    /* All is OK, we store the values. */
    spinModulusUsage = use;
  return res;
}

/** 
 * readSpinResources:
 * @lines: an array of strings ;
 * @nbLines: an integer ;
 * @position: an integer ;
 * @errorMessage: a pointer to a GString or NULL.
 *
 * Returns: 1 if an error occured, 0 otherwise.
 *
 * This is the function called by the core when a spin resource flag is found
 * while reading a resource file. It tries to read, extract and set the resources 
 * it reads from the given file.
 */ 
gboolean readSpinResources(gchar **lines, int nbLines,
                     int position, GString *errorMessage)
{
  GenericRenderingWindow window;
  VisuData *dataObj;
  GError *error;
  gchar **tokens;
  int i;
  gboolean ok;
  VisuElement* ele;
  char *cursor;
  char shape[MAX_LINE_LENGTH];
  float length, u_length, height, u_height;
  int use_color_element, use_element_color_hat;
  int shape_number;
  struct spinResources_struct *str;
  #define NB_SPIN_READ_METHODS 8
  configFileReadFunc readFuncs[NB_SPIN_READ_METHODS] =
    {readElementArrow, readElementElipsoid, readElementShape,
     readSpinColorCone, readSpinColorWheel,
     readSpinHidingMode, readSpinAndAtomic, readSpinModulus};
  gchar *readFlags[NB_SPIN_READ_METHODS] =
    {FLAG_ELEMENT_ARROW, FLAG_ELEMENT_ELIPSOID, FLAG_ELEMENT_SHAPE,
     FLAG_SPIN_CONE_ANGLE, FLAG_SPIN_WHEEL_ANGLE,
     FLAG_SPIN_HIDING_MODE, FLAG_SPIN_AND_ATOMIC, FLAG_SPIN_MODULUS};

  window = visuRenderingWindowGet_current();
  if (window)
    dataObj = visuRenderingWindowGet_visuData(window);
  else
    dataObj = (VisuData*)0;

  /* Read the first keyword. */
  tokens = g_strsplit_set(g_strchug(lines[0]), " \n", 2);

  /* Try to find an element/global resource flag. */
  error = (GError*)0;
  for (i = 0; i < NB_SPIN_READ_METHODS; i++)
    {
      if (!strcmp(g_strstrip(tokens[0]), readFlags[i]))
      {
        ok = readFuncs[i](tokens + 1, 1, position, dataObj, &error);
        if (error)
          {
            if (errorMessage)
            g_string_append_printf(errorMessage, error->message);
            g_error_free(error);
            g_strfreev(tokens);
            return FALSE;
          }
        return ok;
      }
    }
  if (!strcmp(g_strstrip(tokens[0]), "cone_phi_angle") ||
      !strcmp(g_strstrip(tokens[0]), "cone_theta_angle") ||
      !strcmp(g_strstrip(tokens[0]), "color_wheel_angle"))
    {
      g_warning("Deprecated flag at line %d, value ignored.", position);
      return TRUE;
    }

  g_strfreev(tokens);

  /* Finaly read the old format "ele + values". */
  cursor = lines[0];
  error = (GError*)0;
  ele = visuElementRead_fromLine(&cursor, MAX_LINE_LENGTH, position, &error);
  if (error)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, error->message);
      g_error_free(error);
      return FALSE;
    }
  
  /* Retrieving element's resources */
  if(sscanf(cursor, "%s %f %f %f %f %d %d", shape, 
           &height, &u_height, &length, &u_length, 
           &use_color_element, &use_element_color_hat) != 7
     || length <= 0. || u_length <= 0. 
     || height <= 0. || u_height <= 0.)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, 
                         _("WARNING! Parse error at line %d : 4 valid floating point "
                         "values and a shape name must appear after the %s markup.\n"),
                         position, FLAG_RESOURCES_SPIN);
      return FALSE;
    }
  if((shape_number = rspin_shape_name_to_number(shape)) == -1)
    {
      if (errorMessage)
      g_string_append_printf(errorMessage, _("WARNING! Parse error at line %d," 
                                     " the shape '%s' is unknown.\n"), 
                         position, shape);
      shape_number = 0;
    }
  str = getSpinResources(ele);
  str->height                = height;
  str->u_height              = u_height;
  str->length                = length;
  str->u_length              = u_length;
  str->use_element_color     = use_color_element;
  str->use_element_color_hat = use_element_color_hat;
  str->shape                 = shape_number;
  DBG_fprintf(stderr, "resources set successfully for element '%s'\n", ele->name);
  if (dataObj)
    rspin_createShapeSpin(dataObj, ele);
  
  return TRUE;
}

/**
 * exportResourcesRenderingSpin:
 * @data: an empty GString to store the export ;
 * @nbLinesWritten: a pointer to store the number of lines written.
 *
 * This function is called by the core whenever it's needed to export
 * resources. It's in charge of exporting ALL the spin module resources.
 * First it writes global resources in the given @io structure and then
 * writes each element resources using @write_element_resources
 *
 * Returns: TRUE if everything goes right, FALSE otherwise.
 */
gboolean exportResourcesRenderingSpin(GString *data, int *nbLinesWritten,
                              VisuData* dataObj)
{
  GList *pos, *eleList;
  int i;
  struct spinResources_struct *str;
  VisuElement *ele;

  /* If dataObj is given and the rendering method is not spin,
     we return. */
  if (dataObj && pointerOnRenderingSpinMethod != getRenderingMethodInUse())
    return TRUE;

  DBG_fprintf(stderr, "Rendering Spin: exporting element resources...\n");

  g_string_append_printf(data, "# %s\n", DESC_RESOURCES_SPIN);
  *nbLinesWritten = 1;

  g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
  g_string_append_printf(data, "   %s %f %f\n", FLAG_SPIN_CONE_ANGLE,
                   coneOrientation[0], coneOrientation[1]);
  *nbLinesWritten += 2;
  g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
  g_string_append_printf(data, "   %s %f\n", FLAG_SPIN_WHEEL_ANGLE,
                   colorWheel);
  *nbLinesWritten += 2;
  g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
  g_string_append_printf(data, "   %s %s\n", FLAG_SPIN_HIDING_MODE,
                   policyNameSpin[spinPolicy]);
  *nbLinesWritten += 2;
  g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
  g_string_append_printf(data, "   %s %d\n", FLAG_SPIN_AND_ATOMIC,
                   spinAndAtomicRendering);
  *nbLinesWritten += 2;
  g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
  g_string_append_printf(data, "   %s %d\n", FLAG_SPIN_MODULUS,
                   spinModulusUsage);
  *nbLinesWritten += 2;

  /* We create a list of elements, or get the whole list. */
  eleList = (GList*)0;
  if (dataObj)
    {
      for (i = 0; i < dataObj->ntype; i++)
      eleList = g_list_prepend(eleList, (gpointer)dataObj->fromIntToVisuElement[i]);
      pos = eleList;
    }
  else
    pos = visuElementGet_allElements();
  while(pos)
    {
      ele = (VisuElement*)pos->data;
      str = getSpinResources(ele);
      if (str->shape != SPIN_ELEMENT_SHAPE_DEFAULT)
      {
        g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
        g_string_append_printf(data, "   %s %s %s\n", FLAG_ELEMENT_SHAPE,
                         ele->name, rspin_shape_number_to_name(str->shape));
        *nbLinesWritten += 2;
      }
      if (ABS(str->height - SPIN_ELEMENT_HAT_LENGTH_DEFAULT) > 1e-6 ||
        ABS(str->u_height - SPIN_ELEMENT_TAIL_LENGTH_DEFAULT) > 1e-6 ||
        ABS(str->length - SPIN_ELEMENT_HAT_RADIUS_DEFAULT) > 1e-6 ||
        ABS(str->u_length - SPIN_ELEMENT_TAIL_RADIUS_DEFAULT) > 1e-6 ||
        str->use_element_color != SPIN_ELEMENT_TAIL_COLOR_DEFAULT ||
        str->use_element_color_hat != SPIN_ELEMENT_HAT_COLOR_DEFAULT)
      {
        g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
        g_string_append_printf(data, "   %s %s %f %f %f %f %d %d\n",
                         FLAG_ELEMENT_ARROW, ele->name, 
                         str->height, str->u_height, str->length, str->u_length,
                         str->use_element_color, str->use_element_color_hat);
        *nbLinesWritten += 2;
      }
      if (ABS(str->aAxis - SPIN_ELEMENT_AAXIS_DEFAULT) > 1e-6 ||
        ABS(str->bAxis - SPIN_ELEMENT_BAXIS_DEFAULT) > 1e-6 ||
        str->elipsoidColor != SPIN_ELEMENT_ELIP_COLOR_DEFAULT)
      {
        g_string_append_printf(data, "%s:\n", FLAG_RESOURCES_SPIN);
        g_string_append_printf(data, "   %s %s %f %f %d\n",
                         FLAG_ELEMENT_ELIPSOID, ele->name, 
                         str->aAxis, str->bAxis, str->elipsoidColor);
        *nbLinesWritten += 2;
      }
      pos = g_list_next(pos);
    }

  g_string_append_printf(data, "\n");
  *nbLinesWritten += 1;
  if (eleList)
    g_list_free(eleList);

  DBG_fprintf(stderr, "Rendering Spin: element resources succesfully exported\n");
  return TRUE;
}

static void onSpinParametersChanged(VisuData *dataObj, VisuNode *node, gpointer data)
{
  g_return_if_fail(dataObj && node);

  DBG_fprintf(stderr, "Rendering Spin : callback when a spin parameter has been changed.\n");

  visuData_createNodes(dataObj, dataObj->fromIntToVisuElement[node->posElement]);
  g_signal_emit(visu, VISU_GET_CLASS (visu)->OpenGLAskForReDraw_signal_id,
            0 , NULL);
}

/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/
/***************/
/* OpenGL part */
/***************/
/*****************************************************************************/
/*                                                                           */
/*****************************************************************************/

static void drawRoundedHat(float hat_length, float hat_height, float radius, int nlat)
{
  gluCylinder(obj, hat_length, 0, hat_height, nlat, 1);
  glRotatef(180, 1, 0, 0);
  gluDisk(obj, 0, radius, nlat, 1);
  glRotatef(180, 1, 0, 0);
}
static void drawRoundedTail(float tail_length, float tail_height, int nlat)
{
  glTranslatef(0, 0, -tail_height);
  glRotatef(180, 1, 0, 0);
  gluDisk(obj, 0, (tail_length)*1.03, nlat, 1);      
  glRotatef(180, 1, 0, 0);
  gluCylinder(obj, tail_length, tail_length, tail_height, nlat, 1);
}
static void drawEdgedHat(float hat_length, float hat_height)
{
  glBegin(GL_TRIANGLE_FAN);
      
  glNormal3f(hat_height, 0, hat_length);
  glVertex3f(0, 0, hat_height); 
  glVertex3f(hat_length,-hat_length,0);
  glVertex3f(hat_length,hat_length,0);

  glNormal3f(0, hat_height, hat_length);
  glVertex3f(-hat_length,hat_length,0);
       
  glNormal3f(-hat_height, 0, hat_length);
  glVertex3f(-hat_length,-hat_length,0);

  glNormal3f(-hat_height, 0, hat_length);
  glVertex3f(hat_length,-hat_length,0);

  glEnd();

  glBegin(GL_QUADS);

  glNormal3f(0., 0., -1.);
  glVertex3f(hat_length ,hat_length ,0 );
  glVertex3f(hat_length ,-hat_length ,0 );
  glVertex3f(-hat_length ,-hat_length ,0 );
  glVertex3f(-hat_length ,hat_length ,0 );

  glEnd();

}
static void drawEdgedTail(float tail_length, float tail_height)
{
  glBegin(GL_QUADS);

  glNormal3f(0., 0., 1.);
  glVertex3f(tail_length , tail_length , 0 );
  glVertex3f(-tail_length , tail_length , 0 );
  glVertex3f(-tail_length , -tail_length , 0 );
  glVertex3f(tail_length , -tail_length , 0 );

  glNormal3f(0., 0., -1.);
  glVertex3f(tail_length ,tail_length ,-tail_height );
  glVertex3f(tail_length ,-tail_length ,-tail_height );
  glVertex3f(-tail_length ,-tail_length ,-tail_height );
  glVertex3f(-tail_length ,tail_length ,-tail_height );

  glNormal3f(1., 0., 0.);
  glVertex3f(tail_length ,tail_length ,0 );
  glVertex3f(tail_length ,-tail_length ,0 );
  glVertex3f(tail_length ,-tail_length ,-tail_height );
  glVertex3f(tail_length ,tail_length ,-tail_height );

  glNormal3f(-1., 0., 0.);
  glVertex3f(-tail_length ,tail_length ,0 );
  glVertex3f(-tail_length ,tail_length ,-tail_height );
  glVertex3f(-tail_length ,-tail_length ,-tail_height );
  glVertex3f(-tail_length ,-tail_length ,0 );

  glNormal3f(0., 1., 0.);
  glVertex3f(-tail_length ,tail_length ,-tail_height );
  glVertex3f(-tail_length ,tail_length ,0 );
  glVertex3f(tail_length ,tail_length ,0 );
  glVertex3f(tail_length ,tail_length ,-tail_height );

  glNormal3f(0., -1., 0.);
  glVertex3f(-tail_length ,-tail_length ,-tail_height );
  glVertex3f(tail_length ,-tail_length ,-tail_height );
  glVertex3f(tail_length ,-tail_length ,0 );
  glVertex3f(-tail_length ,-tail_length ,0 );

  glEnd();
}

int rspin_createShapeSpin(VisuData *visuData, VisuElement* ele)
{
  int nlatl=0, nlatul=0, nlatoh=0, iele;
  float hatLength, hatRadius, tailLength, tailRadius, *maxModulus, ratio;
  struct spinResources_struct *str;
  OpenGLView *view;

  g_return_val_if_fail(visuData && ele, -1);
 
  str = getSpinResources(ele);
  hatRadius  = str->length;
  tailRadius = str->u_length;
  hatLength  = str->height;
  tailLength = str->u_height;

  view = visuDataGet_openGLView(visuData);
  nlatul = OpenGLViewGet_numberOfFacettes(view, tailRadius) ;
  nlatl = OpenGLViewGet_numberOfFacettes(view, hatRadius);
  nlatoh = OpenGLViewGet_numberOfFacettes(view, hatLength);
  
  DBG_fprintf(stderr, "Rendering Spin : creating arrow for %s,  nlatl = %d,"
            " nlatul = %d, nlatoh = %d\n", 
            ele->name, nlatl, nlatul, nlatoh);

  if (spinModulusUsage)
    maxModulus = (float*)visuDataGet_property(visuData, SPINMAXMODULUS_ID);
  else
    maxModulus = (float*)0;

  /* We always build atomic shapes in case we need them. */
  str->openGLIdentifierAtomic = renderingAtomic_createShape(visuData, ele);

  glNewList(str->openGLIdentifier, GL_COMPILE);
  if (maxModulus)
    {
      iele = *(int*)g_hash_table_lookup(visuData->fromVisuElementToInt, (gpointer)ele);
      ratio = 1. / maxModulus[iele];
      glScalef(ratio, ratio, ratio);
    }
  switch (str->shape)
    {
    case shapeArrow1:
      if (spinAndAtomicRendering)
      glTranslatef(0, 0, tailLength / 2.);
      else
      glTranslatef(0, 0, -(hatLength - tailLength)/2.);
      if(str->use_element_color && str->use_element_color_hat)
      {
        glCallList(visuElementGet_identifierMaterial(ele));
        drawRoundedHat(hatRadius, hatLength, MAX(hatRadius, tailRadius)*1.03, nlatl);
        drawRoundedTail(tailRadius, tailLength, nlatul);
      }
      else if(str->use_element_color)
      {
        drawRoundedHat(hatRadius, hatLength, MAX(hatRadius, tailRadius)*1.03, nlatl);
        glCallList(visuElementGet_identifierMaterial(ele));
        drawRoundedTail(tailRadius, tailLength, nlatul);
      }
      else if(str->use_element_color_hat)
      {
        drawRoundedTail(tailRadius, tailLength, nlatul);
        glTranslatef(0, 0, tailLength);
        glCallList(visuElementGet_identifierMaterial(ele));
        drawRoundedHat(hatRadius, hatLength, MAX(hatRadius, tailRadius)*1.03, nlatl);
      }
      else
      {
        drawRoundedHat(hatRadius, hatLength, MAX(hatRadius, tailRadius)*1.03, nlatl);
        drawRoundedTail(tailRadius, tailLength, nlatul);
      }
      break;
    case shapeArrow2:
      /* This one is a edged arrow. */
      if (spinAndAtomicRendering)
      glTranslatef(0, 0, tailLength / 2.);
      else
      glTranslatef(0, 0, -(hatLength - tailLength)/2.);
      if(str->use_element_color && str->use_element_color_hat)
      {
        glCallList(visuElementGet_identifierMaterial(ele));
        drawEdgedHat(hatRadius, hatLength);
        drawEdgedTail(tailRadius, tailLength);
      }
      else if(str->use_element_color)
      {
        drawEdgedHat(hatRadius, hatLength);
        glCallList(visuElementGet_identifierMaterial(ele));
        drawEdgedTail(tailRadius, tailLength);
      }
      else if(str->use_element_color_hat)
      {
        drawEdgedTail(tailRadius, tailLength);
        glCallList(visuElementGet_identifierMaterial(ele));
        drawEdgedHat(hatRadius, hatLength);
      }
      else
      {
        drawEdgedHat(hatRadius, hatLength);
        drawEdgedTail(tailRadius, tailLength);
      }
      break;
    case shapeElipsoid:
      nlatl = OpenGLViewGet_numberOfFacettes(view, str->bAxis);
      if (str->bAxis == 0.)
      glScalef(1.0, 1.0, 10.);
      else
      glScalef(1.0, 1.0, str->aAxis / str->bAxis);
      if (str->elipsoidColor)
      glCallList(visuElementGet_identifierMaterial(ele));
      gluSphere(obj, str->bAxis, nlatl, nlatl);
      break;
    default:
      DBG_fprintf(stderr, "RenderingSpin : ERROR while drawing objects... Aborting...\n");
      exit(1);
      break;
    }
  glEndList();
   
/*   ele->openGLIdentifier = identifierSpheresSpin + ele->typeNumber; */
  return str->openGLIdentifier;
}

/* This is a method called before the drawing of each node. It's needed to set the
   right positions of each atom but you can apply other treatments if you need.
   Here we also rotate our atom according to the spin theta and phi parameters. */
#ifndef PI
#define PI 3.1415926
#endif

#ifndef DEG2RAD
#define DEG2RAD(x) (0.01745329251994329509 * x)    /* pi / 180 * x */
#endif

void rspin_placeNodeSpin(VisuData *visuData, VisuNode *node, VisuElement* ele)
{
  /* This is the part responsible for the colorisation of
     the atoms according to their spin. */
  float mm[4]; 
  float hsl[3];
  float rgba[4];
  float xyz[3];

  float *spinValues;
  
  float theta_prime;
  float phi_prime;
  /*début rajout*/
  float spherical[3];
  float matrix_rot_theta[3][3];
  float matrix_rot_phi[3][3]; 
  float cartesian[3]; 
  float cartesian_prime[3];
  float cartesian_second[3];
  OpenGLView *view;

  struct spinResources_struct *str;

  view = visuDataGet_openGLView(visuData);
  g_return_if_fail(view);

  /* Test the modulus. */
  spinValues = (float*)visuDataGet_nodeProperty(visuData, node,
                                    SPINVALUES_ID);
  if (spinValues && (spinValues[SPIN_MODULUS] != 0. || spinPolicy == policyAlwaysSpin))
    {
      /* We draw a spin shape. */
      spherical[0] = 1;
      spherical[1] = spinValues[SPIN_THETA];
      spherical[2] = spinValues[SPIN_PHI];

      matrix_rot_theta[0][0] = cos(DEG2RAD(coneOrientation[0]));
      matrix_rot_theta[0][1] = 0;
      matrix_rot_theta[0][2] = -sin(DEG2RAD(coneOrientation[0]));
      matrix_rot_theta[1][0] = 0;
      matrix_rot_theta[1][1] = 1;
      matrix_rot_theta[1][2] = 0;
      matrix_rot_theta[2][0] = sin(DEG2RAD(coneOrientation[0]));
      matrix_rot_theta[2][1] = 0;
      matrix_rot_theta[2][2] = cos(DEG2RAD(coneOrientation[0]));

      matrix_rot_phi[0][0] = cos(DEG2RAD(-coneOrientation[1]));
      matrix_rot_phi[0][1] = -sin(DEG2RAD(-coneOrientation[1]));
      matrix_rot_phi[0][2] = 0;
      matrix_rot_phi[1][0] = sin(DEG2RAD(-coneOrientation[1]));
      matrix_rot_phi[1][1] = cos(DEG2RAD(-coneOrientation[1]));
      matrix_rot_phi[1][2] = 0;
      matrix_rot_phi[2][0] = 0;
      matrix_rot_phi[2][1] = 0;
      matrix_rot_phi[2][2] = 1; 

      cartesian[0] = sin(DEG2RAD(spinValues[SPIN_THETA]))*cos(DEG2RAD(spinValues[SPIN_PHI]));
      cartesian[1] = sin(DEG2RAD(spinValues[SPIN_THETA]))*sin(DEG2RAD(spinValues[SPIN_PHI]));
      cartesian[2] = cos(DEG2RAD(spinValues[SPIN_THETA]));

      /*   fprintf(stderr, "%f %f %f --> ", spherical[0], spherical[1], spherical[2]); */

      matrix_productVector(cartesian_prime, matrix_rot_phi, cartesian);
      matrix_productVector(cartesian_second, matrix_rot_theta, cartesian_prime);
      /*   square_matrix_product(matrix_rot_phi, cartesian_second, cartesian_ter, 3); */

      matrix_cartesianToSpherical(spherical, cartesian_second);

      /*   fprintf(stderr, "%f %f %f \n", spherical[0], spherical[1], spherical[2]); */

      /*   theta_prime = spherical[1] - coneOrientation[0]; */
      /*   phi_prime = spherical[2]; */

      /*   /\* fin modifs *\/ */
      /*   theta_prime = fModulo(theta_prime, 360); */

      /*   if(theta_prime > 180) */
      /*     { */
      /*       theta_prime = 360 - theta_prime; */
      /*       phi_prime += 180; */
      /*       phi_prime = fModulo(phi_prime, 360); */
      /*     } */

      /*   phi_prime -= coneOrientation[1]; */
      /*   phi_prime = fModulo(phi_prime, 360);  /\* Probably useless *\/ */

      theta_prime = spherical[1];
      phi_prime = spherical[2];

      hsl[2] = 1 - theta_prime/180.;

      hsl[0] = fModulo(phi_prime - colorWheel, 360) / 360.;

      /* FIN ALGO COLORISATION */

      hsl[1] = 1;
  
      color_HSLtoRGB(mm, hsl);

      mm[3] = ele->rgb[3];
  
      /* The following is the part responsible for the rotation 
       of the atoms according to their spins. */

      visuDataGet_nodePosition(visuData, node, xyz);

      glPushMatrix();

      /* Translate to the rendering position. */
      glTranslated(xyz[0] - view->box->dxxs2,
               xyz[1] - view->box->dyys2,
               xyz[2] - view->box->dzzs2);


      /* If we need to draw also an atom shape. */
      if (spinAndAtomicRendering)
      {
        glCallList(visuElementGet_identifierMaterial(ele));
        str = (struct spinResources_struct*)getSpinResources(ele);
        glCallList(str->openGLIdentifierAtomic);
      }

      /* We rotate the spin shape into the right direction. */
      glRotated(spinValues[SPIN_PHI], 0, 0, 1);  
      glRotated(spinValues[SPIN_THETA], 0, 1, 0); 

      /* We scale the shape if required. */
      if (spinModulusUsage)
      {
        glScalef(spinValues[SPIN_MODULUS],
               spinValues[SPIN_MODULUS],
               spinValues[SPIN_MODULUS]);
/*      glScalef(1.0, 1.0, str->modulusProp * spinValues[SPIN_MODULUS]); */
      }

      /* We change its color if required. */
      if (visuData->setColor)
      {
        visuData->setColor(visuData, rgba, ele, node);
        setOpenGlMaterial(ele->material, rgba);
      }
      else
      setOpenGlMaterial(ele->material, mm);

      /* We finaly put the spin shape. */
      glCallList(ele->openGLIdentifier);

      glPopMatrix();
    }
  else
    {
      /* Case modulus is null. */
      if (spinPolicy == policyAtomicNullSpin || spinAndAtomicRendering)
      {
        visuDataGet_nodePosition(visuData, node, xyz);

        glPushMatrix();
  
        glTranslated(xyz[0] - view->box->dxxs2,
                   xyz[1] - view->box->dyys2,
                   xyz[2] - view->box->dzzs2);

        glCallList(visuElementGet_identifierMaterial(ele));
        str = (struct spinResources_struct*)getSpinResources(ele);
        glCallList(str->openGLIdentifierAtomic);
        glPopMatrix();
      }
    }
}

Generated by  Doxygen 1.6.0   Back to index