#ifndef lint
static char *sccsid = "@(#)surface.c	1.1 (Steve Hill) 3/9/90";
#endif

/* surface.c
 *
 * Routines to create and manipulate surface descriptions.
 * Initially surfaces shall be described by their reflective properties.
 * Ultimately these may become modifiable using a pattern function.
 */

#include <stdio.h>

#include "basetype.h"
#include "error.h"
#include "colour.h"
#include "surface.h"


/* default_surface, default_ambient, default_diffuse,
 * default_specular, default_power
 *
 * This surface is used as the default for solids.
 */

colour_t	default_ambient = DEFAULT_AMBIENT,
		default_diffuse = DEFAULT_DIFFUSE,
		default_mirror  = DEFAULT_MIRROR,
		default_transmit = DEFAULT_TRANSMIT;

real_t		default_index    = DEFAULT_INDEX,
		default_specular = DEFAULT_SPECULAR,
		default_power    = DEFAULT_POWER;

surface_t
default_surface =
{
	&default_ambient,
	&default_diffuse,
	&default_mirror,
	&default_transmit,
	DEFAULT_INDEX,
	DEFAULT_SPECULAR,
	DEFAULT_POWER
};


/* Surface
 *
 * Allocate and initialise a surface structure.
 */

surface_t *
Surface(ambient, diffuse, mirror, transmit, index, specular, power)
colour_t	*ambient, *diffuse, *mirror, *transmit;
real_t		index, specular, power;
{
	surface_t	*surface;

	surface = (surface_t *) malloc(sizeof(surface_t));
	if (surface == SurfaceNull)
		FatalError(__FILE__, __LINE__, "Surface: out of memory");

	surface->ambient  = ambient;
	surface->diffuse  = diffuse;
	surface->mirror   = mirror;
	surface->transmit = transmit;
	surface->index    = index;
	surface->specular = specular;
	surface->power    = power;

	return(surface);
}


/* SurfaceCopy
 *
 * Duplicate a surface, and all sub parts.
 */

surface_t *
SurfaceCopy(surface)
surface_t	*surface;
{
	if (surface == SurfaceNull)
		return(SurfaceNull);

	return(Surface(ColourCopy(surface->ambient),
		       ColourCopy(surface->diffuse),
		       ColourCopy(surface->mirror),
		       ColourCopy(surface->transmit),
		       surface->index,
		       surface->specular,
		       surface->power));
}


/* SurfaceFree
 *
 * Deallocate surface and all sub-structures.
 */

void
SurfaceFree(surface)
surface_t	*surface;
{
	if (surface == SurfaceNull)
		return;

	ColourFree(surface->ambient);
	ColourFree(surface->diffuse);
	ColourFree(surface->mirror);
	ColourFree(surface->transmit);
	(void) free((char *) surface);
}


/* SurfacePrint
 *
 * Print a surface to a file.
 */

void
SurfacePrint(file, surface)
FILE		*file;
surface_t	*surface;
{
	if (surface == SurfaceNull)
	{
		fprintf(file, "Null Surface\n");
		return;
	}

	ColourPrint(file, surface->ambient);
	ColourPrint(file, surface->diffuse);
	ColourPrint(file, surface->mirror);
	ColourPrint(file, surface->transmit);
	(void) fprintf(file, "%f, %f, %f",
		       surface->index, surface->specular, surface->power);
}
