/**************************************************************************
  Copyright (C) 1992 Guy Moreillon
  All rights reserved.

  This software may be freely copied, modified, and redistributed
  provided that this copyright notice is preserved on all copies.

  You may not distribute this software, in whole or in part, as part of
  any commercial product without the express consent of the authors.

  There is no warranty or other guarantee of fitness of this software
  for any purpose.  It is provided solely "as is".
**************************************************************************/
/**************************************************************************

				RAD
		       (Interactive Radiosity)
		    	    Version 1.0
			       1992		    	    
		    	    
		  
		    	  Guy Moreillon
		    	  
**************************************************************************/

/**************************************************************************
  Fichier	: iowrite.c
  Description	: Fonctions utilisees pour l'ecriture du fichier gview
**************************************************************************/

#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "types.h"
#include "macros.h"
#include "misc.h"
#include "iowrite.h"

typedef void (*ACTION)(TRIANGLEP tri, FILE *gview);

int	npoint, npol;

void B_to_RGB(unsigned char *rgb,
	      VECTOR	    B)
/**************************************************************************
  But	: Converti une valeur de radiosite en une valeur RGB sur 3 octets
  Entree: rgb :	la valeur RGB
	  B   :	la valeur de radiosite
  Sortie: neant
**************************************************************************/
{
  VECTOR    tmp;

  clip_rgb(tmp, B);

  rgb[0] = (unsigned char)(tmp[0] * 255);
  rgb[1] = (unsigned char)(tmp[1] * 255);
  rgb[2] = (unsigned char)(tmp[2] * 255);
}

void w_pb_gv_poly(TRIANGLEP tri,
		  FILE	    *gview)
/**************************************************************************
  But	: Ecrit les points et leur couleur associee du polygone dans un
	  fichier au format utilisable par gview
  Entree: tri :	    polygone
	  gview :   le fichier
  Sortie: neant
**************************************************************************/
{
  int		i;
  unsigned char rgb[3];

  for(i = 0; i < tri->tri.poly.nb_v; i++)
    {
      fprintf(gview, "v3f {%f %f %f}\n",
	      tri->tri.poly.vertex[i].point[0],
	      tri->tri.poly.vertex[i].point[1],
	      tri->tri.poly.vertex[i].point[2]);
      tri->tri.poly.vertex[i].db = npoint++;
      B_to_RGB(rgb, tri->tri.poly.vertex[i].B);
      fprintf(gview, "cpack {0x%02x%02x%02x}\n", rgb[2], rgb[1], rgb[0]);
    };
}

void w_pol_gv_poly(TRIANGLEP	tri,
		   FILE		*gview)
/**************************************************************************
  But	: Ecrit les polygones constituants de tri (ou tri) sur fichier
	  dans un format utilisable par gview.
  Entree: tri :	    polygone/subdivision
	  gview :   le fichier
  Sortie: neant
**************************************************************************/
{
  int i, j;

  if (tri->type == poly_type)
    {
      if (tri->tri.poly.sons != NULL)
        w_pol_gv_poly(tri->tri.poly.sons, gview);
      else
        {
	  fprintf(gview, "polygon {");
          for(i = 0; i < 3; i++)
	    fprintf(gview, "cpack[%d] v3f[%d] ",
		    tri->tri.poly.vertex[i].db,
		    tri->tri.poly.vertex[i].db);
	  fprintf(gview, "}\n");
	  npol++;
        };
    }
  else
    for(j = 0; j < 4; j++)
      if (tri->tri.subdiv.elements[j].sons != NULL)
	w_pol_gv_poly(tri->tri.subdiv.elements[j].sons, gview);
      else
        {
	  VERTEXP   array = tri->tri.subdiv.dad->tri.poly.vertex;

	  fprintf(gview, "polygon {");
          for(i = 0; i < 3; i++)
	    fprintf(gview, "cpack[%d] v3f[%d] ",
		    array[tri->tri.subdiv.elements[j].vertex[i]].db,
		    array[tri->tri.subdiv.elements[j].vertex[i]].db);
	  fprintf(gview, "}\n");
	  npol++;
        };
}

void visit_polys(OBJECT_OP object, ACTION action, FILE *file)
/**************************************************************************
  But	: Parcours tous les polygones de l'objet en effectuant l'action
	  specifiee sur chacun
  Entree: object    : l'objet
	  action    : l'action
	  file	    : le fichier de sortie
  Sortie: neant
**************************************************************************/
{
  OBJECT_OP obj;
  int	    i;

  switch(object->type) {
    case assembly_type:
      for(obj = object->object.assembly.sons; obj != NULL; obj = obj->next)
	visit_polys(obj, action, file);
      break;
    case composite_type:
      for(obj = object->object.composite.sons; obj != NULL; obj = obj->next)
	visit_polys(obj, action, file);
      break;
    case pure_type:
      for(i = 0; i < object->object.pure.nb_polys; i++)
	action(&(object->object.pure.polys[i]), file);
      break;
    default:
      break;
  }
}

void write_gview(char *name, SCENE_OP scene)
/**************************************************************************
  But	: Ecrit l'etat actuel de la scene dans un fichier, dans un format
	  utilisable par gview
  Entree: name	    : le nom du fichier de sortie
	  scene	    : la scene
  Sortie: neant
**************************************************************************/
{
  FILE	    *gview;
  int	    i;

  printf("\nWriting results in file %s\n", name);

  npoint = npol = 0;

  if ((gview = fopen(name, "w")) == NULL)
    printf("Can't open file %s !\n", name), exit(1);

  fprintf(gview, "scope {\n");

  visit_polys(scene->scene, w_pb_gv_poly, gview);

  visit_polys(scene->scene, w_pol_gv_poly, gview);

  fprintf(gview, "instance {\n"); 
  for(i = 0; i < npol; i++)
    fprintf(gview, "  polygon[%d]\n", i);
  fprintf(gview,  "  }\n}");

  fclose(gview);
}

