/*   EXTRAITS DE LA LICENCE
	Copyright CEA, contributeurs : Luc BILLARD et Damien
	CALISTE, laboratoire L_Sim, (2001-2006)
  
	Adresse mèl :
	BILLARD, non joignable par mèl ;
	CALISTE, damien P caliste AT cea 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 et Damien
	CALISTE, laboratoire L_Sim, (2001-2006)

	E-mail address:
	BILLARD, not reachable any more ;
	CALISTE, damien P caliste AT cea 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.
*/
#ifndef CAMERA_H
#define CAMERA_H

#include <glib.h>

/**
 * PI180:
 *
 * Value of pi / 180.
 */
#define PI180 0.017453292522

struct OpenGLView_struct;
/**
 * OpenGLView:
 *
 * Short name for #OpenGLView_struct structures.
 */
typedef struct OpenGLView_struct OpenGLView;


/**
 * OpenGLCamera_struct:
 * @d_red: a factor for perspective from 1. to inifnity. With one, the nose of
 *         the observer is completly set on the rendered object, and the size
 *         of the observer is neglectible compared to the size of the object.
 * @gr: a private value equal to d_red / (d_red - 1.) ;
 * @theta: the theta angle in spherical coordinates of the position of the observer ;
 * @phi: the phi angle in spherical coordinates of the position of the observer ;
 * @omega: rotation of the observer on itself ;
 * @xs: a value for translation of the viewport on x axis ;
 * @ys: a value for translation of the viewport on y axis ;
 * @gross: a value of zoom.
 * 
 * Values to define the position of the observer.
 */
struct OpenGLCamera_struct
{
  /* Perspective. */
  double d_red;
  double gr; /* equal to d_red / (d_red - 1.) */
  /* Orientation. */
  double theta, phi, omega;
  /* Position. */
  double xs, ys;
  /* Zoom. */
  double gross;
};
/**
 * OpenGLCamera:
 *
 * A short way to adress #OpenGLCamera_struct objects.
 */
typedef struct OpenGLCamera_struct OpenGLCamera;

/**
 * MASK_THETA:
 *
 * Value used in the openGLCameraSet_thetaPhiOmega() method to store the tetha angle.
 */
#define MASK_THETA (1 << 1)
/**
 * MASK_PHI:
 *
 * Value used in the openGLCameraSet_thetaPhiOmega() method to store the phi angle.
 */
#define MASK_PHI   (1 << 2)
/**
 * MASK_OMEGA:
 *
 * Value used in the openGLCameraSet_thetaPhiOmega() method to store the omega angle.
 */
#define MASK_OMEGA   (1 << 3)
/**
 * openGLCameraSet_thetaPhiOmega:
 * @view: a valid #OpenGLView object ;
 * @valueTheta: a floatinf point value in degrees ;
 * @valuePhi: a floating point value in degrees ;
 * @valueOmega: a floating point value in degrees ;
 * @mask: to specified what values will be changed.
 *
 * Change the orientation of the camera to the specified angles.
 *
 * Returns: TRUE if the signal OpenGLAskForReDraw should be emitted.
 */
int openGLViewSet_thetaPhiOmega(OpenGLView *view, float valueTheta,
				float valuePhi, float valueOmega, int mask);
/**
 * MASK_XS:
 *
 * Value used in the openGLCameraSet_XsYs() method to store the horizontal offset.
 */
#define MASK_XS (1 << 1)
/**
 * MASK_YS:
 *
 * Value used in the openGLCameraSet_XsYs() method to store the vertical offset.
 */
#define MASK_YS   (1 << 2)
/**
 * openGLCameraSet_XsYs:
 * @view: a valid #OpenGLView object ;
 * @valueX: a floatinf point value in the bounding box scale
 *          (1 is the size of the bounding box) ;
 * @valueY: a floating point value in bounding box scale ;
 * @mask: to specified what values will be changed.
 *
 * Change the point where the camera is pointed to.
 *
 * Returns: TRUE if the signal OpenGLAskForReDraw should be emitted.
 */
int openGLViewSet_XsYs(OpenGLView *view, float valueX, float valueY, int mask);
/**
 * openGLCameraSet_gross:
 * @view: a valid #OpenGLView object ;
 * @value: a positive floating point value.
 *
 * Change the value of the camera zoom value. If the value is higher than 10
 * it is set to 10 and if the value is negative it is set to 0.001.
 *
 * Returns: TRUE if the signal OpenGLAskForReDraw should be emitted.
 */
int openGLViewSet_gross(OpenGLView *view, float value);
/**
 * openGLViewSet_persp:
 * @view: a valid #OpenGLView object ;
 * @value: a floating point value greater than 1.1.
 *
 * Change the value of the camera perspective value and put it in
 * bounds if needed.
 *
 * Returns: TRUE if the signal OpenGLAskForReDraw should be emitted.
 */
int openGLViewSet_persp(OpenGLView *view, float value);

/**
 * OpenGLBox_struct:
 * @extens : not used ;
 * @dxxs2: the square value of the norm of the x vector of the box ;
 * @dyys2: the square value of the norm of the y vector of the box ;
 * @dzzs2: the square value of the norm of the z vector of the box ;
 * @p1: the coordinates of the point (0,0,0) ;
 * @p2: the coordinates of the point (1,0,0) ;
 * @p3: the coordinates of the point (1,1,0) ;
 * @p4: the coordinates of the point (0,1,0) ;
 * @p5: the coordinates of the point (0,0,1) ;
 * @p6: the coordinates of the point (1,0,1) ;
 * @p7: the coordinates of the point (1,1,1) ;
 * @p8: the coordinates of the point (0,1,1).
 *
 * Values to describe the box where the render is done. These values are 
 * linked to a #VisuData object (the currentVisuData pointer) and valid as
 * long as this object is available. This should migrate to the #VisuData object
 * in future releases.
 */
struct OpenGLBox_struct
{
  double extens; /* makes changes in modelize, project, and numberOfFacette */
  
  double dxxs2, dyys2, dzzs2;
  double p1[3], p2[3], p3[3], p4[3], p5[3], p6[3], p7[3], p8[3];
};
/**
 * OpenGLBox:
 *
 * A short way to identify #OpenGLBox_struct object.
 */
typedef struct OpenGLBox_struct OpenGLBox;

/**
 * OpenGLWindow_struct:
 * @width : the width of the window ;
 * @height : the height of the window ;
 * @near : the beginning of the viewport on z axis (z for observer) ;
 * @far : the end of the viewport on z axis (z for observer) ;
 * @left : the left of the viewport on x axis ;
 * @right : the right of the viewport on x axis ;
 * @bottom : the bottom of the viewport on y axis ;
 * @top : the top of the viewport on y axis ;
 *
 * Values to describe the window where the render is done.
 */
struct OpenGLWindow_struct
{
  guint width, height;
  double near, far;
  double left, right, bottom, top;
};
/**
 * OpenGLWindow:
 *
 * A short way to identify #OpenGLWindow_struct object.
 */
typedef struct OpenGLWindow_struct OpenGLWindow;
/**
 * OpenGLViewSet_windowSize:
 * @view: a valid #OpenGLView object (can be NULL);
 * @width: the new horizontal size ;
 * @height: the new vertical size.
 *
 * It changes the size of the OpenGl area and reccompute the OpenGL viewport.
 * Warning : it doesn't change the size of the window. If the @view is NULL, then
 * only the OpenGl area is changed (usefull when no VisuData is available).
 *
 * Returns: TRUE if the signals OpenGLWidthHeight, OpenGLFacetteChanged and
 *          OpenGLAskForReDraw should be emitted.
 */
int OpenGLViewSet_windowSize(OpenGLView *view, guint width, guint height);
/**
 * OpenGLViewGet_fileUnitPerPixel:
 * @view: a valid #OpenGLView object.
 *
 * This method is used to know the ratio of a pixel with the unit of the file.
 * WARNING : this method is valid only when the camera is position at infinity.
 * 
 * Returns: how much of a unit of file is in a pixel.
 */
float OpenGLViewGet_fileUnitPerPixel(OpenGLView *view);
/**
 * OpenGLViewGet_screenAxes:
 * @view: a valid #OpenGLView.
 * @xAxis: three float values representing x axis ;
 * @yAxis: three float values representing y axis.
 *
 * This method is used to get the coordinates in box frame of x axis and y axis
 * of the current camera view.
 */
void OpenGLViewGet_screenAxes(OpenGLView *view, float xAxis[3], float yAxis[3]);



/**
 * OpenGLView_struct:
 * @camera: a #OpenGLCamera structure;
 * @window: a #OpenGLWindow structure;
 * @box: a #OpenGLBox structure;
 *
 * A container structure to deal with OpenGL observer position, size of rendering
 * viewport...
 */
struct OpenGLView_struct
{
  OpenGLCamera *camera;
  OpenGLWindow *window;
  OpenGLBox *box;
};

/**
 * OpenGLViewNew:
 *
 * Create a new #OpenGLView object with default values.
 *
 * Returns: the newly created object (to be free with OpenGLViewFree()).
 */
OpenGLView* OpenGLViewNew();
/**
 * OpenGLViewFree:
 * @view: a valid #OpenGLView object.
 *
 * Free the given @view.
 */
void OpenGLViewFree(OpenGLView *view);
/**
 * OpenGLViewCopy:
 * @view: a valid #OpenGLView object.
 *
 * Copy operator (newly #OpenGLView created with g_malloc() to be freed be g_free()).
 *
 * Returns: a newly allocated #OpenGLView with same values than @view.
 */
OpenGLView* OpenGLViewCopy(OpenGLView *view);
/**
 * OpenGLViewGet_numberOfFacettes:
 * @view: a valid #OpenGLView object ;
 * @dimension: the size of the object which asks for its number of facettes.
 *
 * This is a function to get the number of "facettes" advised
 * by the server (according to its policy on rendering)
 * to draw an object according to a given dimension.
 *
 * Returns: the number of facettes the object should used.
 */
int OpenGLViewGet_numberOfFacettes(OpenGLView *view, float dimension);

/**
 * openGLViewCompute_matrixAndView:
 * @view: a valid #OpenGLView object.
 *
 * This method is used to set the projection and the OpenGL viewport.
 * It's used by VisuData and should not be called elsewhere.
 */
void openGLViewCompute_matrixAndView(OpenGLView* view);

/**
 * OpenGLViewSet_precision:
 * @value: a positive value (100 is normal precision).
 *
 * This function change the value of the parameter precisionOfRendering. It
 * changes the number of facettes advised for every objects. It allows to
 * increase or decrease the number of polygons drawn and thus acts on the
 * speed of rendering.
 *
 * Returns: TRUE if the signals OpenGLFacetteChanged and
 *          OpenGLAskForReDraw should be emitted.
 */
int OpenGLViewSet_precision(float value);
/**
 * OpenGLViewGet_precision:
 *
 * This function retrieve the value of the parameter precisionOfRendering.
 *
 * Returns: the actual precision.
 */
float OpenGLViewGet_precision();
/**
 * openGLViewRotate_box:
 * @view: a valid #OpenGLView object ;
 * @dTheta: a float value ;
 * @dPhi: a float value ;
 * @angles: a storing area two floats.
 *
 * This methods rotates the camera of the given @view of (@dTheta, @dPhi) and
 * put new theta and phi angles in @angles, first being theta and second phi.
 */
void openGLViewRotate_box(OpenGLView *view, float dTheta, float dPhi, float angles[2]);
/**
 * openGLViewRotate_box:
 * @view: a valid #OpenGLView object ;
 * @dTheta: a float value ;
 * @dPhi: a float value ;
 * @angles: a storing area three floats.
 *
 * This methods rotates the camera of the given @view of (@dTheta, @dPhi).
 * @dTheta is taken as displacement along camera x axis and dPhi along camera y axis.
 * Then, computations are done to obtain new theta, phi and omega values. They are
 * put in @angles, first being theta, second phi and third omega.
 */
void openGLViewRotate_camera(OpenGLView *view, float dTheta, float dPhi, float angles[3]);


/**
 * OpenGLViewInit:
 *
 * This method is used by V_Sim during initilization process and should
 * not be called.
 */
void OpenGLViewInit();

#endif
