/**************************************************************************
  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	: iosave.c
  Description	: Fonctions utilisees pour l'ecriture de donnees sur fichier
**************************************************************************/

#include <stdio.h>
#include <math.h>
#include "types.h"
#include "macros.h"
#include "io.h"
#include "rad.h"
#include "iosave.h"

BOOLEAN save_textures(FILE *statef, SCENE_OP scene)
/**************************************************************************
  But	: Ecrit l'etat actuel du tableau des textures
  Entree: statef    : le fichier de sortie
	  scene	    : la scene
  Sortie: TRUE si l'operation a reussi, FALSE sinon
**************************************************************************/
{
  if (fwrite(scene->textures, sizeof(TEXTURE), MAX_TEX, statef) != MAX_TEX)
    return FALSE;

  return TRUE;
}

BOOLEAN save_subdiv(TRIANGLEP	tri,
		    FILE	*statef)
/**************************************************************************
  But	: Ecrit l'etat actuel de la subdivision avec ses subdivisions dans
	  le fichier ouvert, dans un format binaire dedie
  Entree: tri	    : la subdivision
	  statef   : le fichier de sortie
  Sortie: TRUE si l'operation a reussi, FALSE sinon
**************************************************************************/
{
  register  int i;
  int		start_subdiv = START_SUBDIV, end_subdiv = END_SUBDIV;

  for(i = 0; i < 4; i++)
    {
      fwrite(&start_subdiv, sizeof(int), 1, statef);
      fwrite(&(tri->tri.subdiv.elements[i]), sizeof(ELEMENT), 1, statef);
      if (tri->tri.subdiv.elements[i].sons != NULL)
	{
	  putc(TRUE, statef);
          if (!save_subdiv(tri->tri.subdiv.elements[i].sons, statef))
	    return FALSE;
	}
      else
	putc(FALSE, statef);
      fwrite(&end_subdiv, sizeof(int), 1, statef);
    };

  return TRUE;
}

BOOLEAN save_poly(TRIANGLE	*tri,
		  FILE		*statef)
/**************************************************************************
  But	: Ecrit l'etat actuel du polygone avec ses subdivisions dans le
	  fichier ouvert, dans un format binaire dedie
  Entree: tri	    : le polygone
	  statef   : le fichier de sortie
  Sortie: TRUE si l'operation a reussi, FALSE sinon
**************************************************************************/
{
  fwrite(&(tri->tri.poly), sizeof(POLY), 1, statef);

  fwrite(tri->tri.poly.vertex, sizeof(VERTEX),
	 tri->tri.poly.nb_v, statef);

  if (tri->tri.poly.sons != NULL)
    {
      putc(TRUE, statef);
      if (!save_subdiv(tri->tri.poly.sons, statef))
        return FALSE;
    }
  else
    putc(FALSE, statef);

  return TRUE;
}

BOOLEAN save_pure(OBJECT_OP	obj,
		  FILE		*statef)
/**************************************************************************
  But	: Ecrit l'etat actuel de l'objet pure dans le fichier ouvert,
	  dans un format binaire dedie
  Entree: obj	    : l'objet
	  statef   : le fichier de sortie
  Sortie: TRUE si l'operation a reussi, FALSE sinon
**************************************************************************/
{
  register  int	i;
  int		start_poly = START_POLY, end_poly = END_POLY;

  fwrite(&(obj->object.pure), sizeof(PURE_O), 1, statef);

  for(i = 0; i < obj->object.pure.nb_polys; i++)
    {
      fwrite(&start_poly, sizeof(int), 1, statef);
      if (!save_poly(&(obj->object.pure.polys[i]), statef))
        return FALSE;
      fwrite(&end_poly, sizeof(int), 1, statef);
    };

  return TRUE;
}

BOOLEAN save_object(OBJECT_OP	obj,
		    FILE	*statef)
/**************************************************************************
  But	: Ecrit l'etat actuel de l'objet dans le fichier ouvert,
	  dans un format binaire dedie
  Entree: obj	    : l'objet
	  statef   : le fichier de sortie
  Sortie: TRUE si l'operation a reussi, FALSE sinon
**************************************************************************/
{
  OBJECT_OP	son;
  Object_type	end_object = unknown;

  if (obj == NULL)
    return FALSE;

  fwrite(&(obj->type), sizeof(Object_type), 1, statef);
  fwrite(obj->name, NAME_SIZE, 1, statef);

  switch (obj->type) {
    case assembly_type :
      for(son = obj->object.assembly.sons; son != NULL; son = son->next)
	if (!save_object(son, statef))
	  return FALSE;
      fwrite(&end_object, sizeof(Object_type), 1, statef);
      break;
    case composite_type :
      for(son = obj->object.composite.sons; son != NULL; son = son->next)
	if (!save_object(son, statef))
	  return FALSE;
      fwrite(&end_object, sizeof(Object_type), 1, statef);
      break;      
    case pure_type :
      if (!save_pure(obj, statef))
	return FALSE;
      break;
    default : 
      Bye_bye("Major Bug in the datas... Aborting.\n");
    };

  fwrite(&end_object, sizeof(Object_type), 1, statef);

  return TRUE;
}

BOOLEAN save_state(FILE *statef, SCENE_OP scene)
/**************************************************************************
  But	: Ecrit l'etat actuel du calcul de la scene dans un fichier,
	  dans un format binaire dedie
  Entree: statef    : le fichier (ouvert)
	  scene	    : la scene
  Sortie: TRUE si l'operation a reussi, FALSE sinon
**************************************************************************/
{
  if (fwrite(&(scene->state), sizeof(STATE_BLK), 1, statef) != 1)
    return FALSE;

  if (!save_object(scene->scene, statef))
    return FALSE;

  if (!save_textures(statef, scene))
    return FALSE;

  fclose(statef);
  
  return TRUE;
}

