#ifndef SPHERE_H
#define SPHERE_H

#include "types.h"
#include "globj.h"
#include "glhand.h"
#include "gloutils.h"

globj_class_t globj_class_sphere ;

zone_t zone_sphere ;
action_t action_sphere_detail ;
action_t action_sphere_laminate ;

typedef struct vertex_s
{
  vector position ;
  int triangles[6] ; /* there can be up to 6 triangles using a vertex */
  vector normal ;
  GLfloat color[4] ; /* FIXME: convert colors to byte ... ? */
} vertex_t, *vertex_p ;

typedef struct triangle_s
{
  int vertices[3]; /* vertices, clockwise */
  vector normal; /* normal vector */
  int triangles[4] ; /* "sons" of this triangle */
  int root ; /* "father" of this triangle */
} triangle_t, *triangle_p ;

/*
            v1              t1's v1 is v1
           /  \             t2's v2 is v2
          / t1 \            t3's v3 is v3
         /------\           t4's v1 is pointing down
        / \ t4 / \
       /   \  /   \
      / t3  \/ t2  \
     v3------------v2
 */

typedef struct sphere_s {
  vertex_t* vertices ;
  triangle_t* triangles ;
  int n_lines ; /* Segment count */       /* --  Ln  -- */
  int n_vertices ; /* initially 12 */     /* --  Vn  -- */
  int n_triangles ;  /* initially 20 */   /* --  Fn  -- */
  int n_internals ; /* triangles which are not real faces . initially 0 */
  int n_roots ; /* toplevel triangles (constant) */
  int depth ; /* 0 = 20 triangles, 1 = 20 internals + XXX new ... */
} sphere_t, *sphere_p ;

typedef void(*sphere_drawtriangle_f)(sphere_t*,triangle_t*) ;

sphere_t* sphere_new      () ;
void      sphere_delete   (sphere_t*) ;
void      sphere_drawslow (sphere_t*) ;
void      sphere_drawfast (sphere_t*) ; 
void      sphere_drawopt  (sphere_t*,glcam_t*,int,int) ; 
void      sphere_drawtriangle(sphere_t*, triangle_t*, opengldata_t*,
			      glcam_t*,int,int,int*,sphere_drawtriangle_f) ;
void      sphere_detail   (sphere_t*) ;
void      sphere_computevertexnormal(vertex_t*, sphere_t*);
void      sphere_computenormals(sphere_t*);
void      sphere_maptosurface (sphere_t* sphere, vector* point) ;
void      vertex_setcolor (vertex_t*, float, float, float, float) ;
int       triangle_computearea (double x[3], double y[3]) ;
int sphere_findtriangleindex (sphere_t* sphere, triangle_t* triangle) ;


void sphere_drawtriangle_gl_smoothlight (sphere_t* s, triangle_t* t) ;
void sphere_drawtriangle_gl_flatlight (sphere_t* s, triangle_t* t) ;
void sphere_drawtriangle_gl_smoothcolor (sphere_t* s, triangle_t* t) ;
void sphere_drawtriangle_gl_flatcolor (sphere_t* s, triangle_t* t) ;
void sphere_drawtriangle_gl_selection (sphere_t* s, triangle_t* t) ;
void sphere_drawtriangle_gl_highlight (sphere_t* s, triangle_t* t) ;

/*
<LordBrain> formalisons un peu ces formules justement ! Soient Vn le nb de sommets, Ln le nb de segments et Fn le nb de faces ...
<Skaya> V0=12 L0=30 F0=20 pour un icosaedre.
<Skaya> Vn+1 = Vn + Ln
<Skaya> Ln+1 = 2*Ln + 3*Fn
<Skaya> Fn+1 = 4*Fn
*/

/* Lamination Control Structures */

typedef struct {
  char *name ;      /* Planet's name */
 
  /*
    Readjustement parameters
    -- minimal altitude : radius - seafactor
    -- maximal altitude : radius + landfactor
  */
  
  float radius ;
  float sealevel ;
  float seafactor ;
  float landfactor ;

  /*
    Colors parameters
    -- include alpha variation ?
  */

  unsigned int n_colors ;
  float collevels ;
  GLfloat **startcolor ;
  GLfloat **endcolor ;

  /*
    Lamination parameters
  */
  unsigned int startdepth ;
  unsigned int enddepth ;
  unsigned int *n_lamination ;
  float *lamination_level ;
  
} planetdata_t ;

#endif
