/*
 * surface.c
 *
 * Copyright (C) 1989, 1991, Craig E. Kolb
 * 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".
 *
 * $Id$
 *
 * $Log$
 */
#include "atmosphere.h"
#include "surface.h"

#define blend(a, b, p, q)	(a * p + b * q)

Color Black = {0., 0., 0.};

/*
 * Create and return pointer to surface with given properties.
 */
Surface *
SurfaceCreate()
{
	Surface *stmp;

	stmp = (Surface *)Malloc(sizeof(Surface));
	stmp->amb = stmp->diff = stmp->spec = Black;
	stmp->coef = stmp->refl = stmp->transp =
		stmp->translucency = stmp->stcoef = 0.;
	stmp->kref = DEFAULT_INDEX;
	stmp->noshadow = FALSE;

	stmp->name = (char *)NULL;
	stmp->atmos = (Atmosphere *)NULL;
	stmp->next = (Surface *)NULL;

	return stmp;
}

Surface *
SurfaceCopy(surf)
Surface *surf;
{
	Surface *res;

	if (!surf)
		return (Surface *)NULL;

	res = SurfaceCreate();
	*res = *surf;
	res->next = (Surface *)NULL;
	res->name = (char *)NULL;
	/* Also have to copy atmospheric effects.*/
	res->atmos = AtmosphereCopy(surf->atmos);
	return res;
}

/*
 * Compute combination of two surfaces. Resulting surface is copied into surf1.
 */
void
SurfaceBlend(surf1, surf2, p, q)
Surface *surf1, *surf2;
Float p, q;
{
	/*
 	 * P is weight of surf1.  q is weight of surf2.
	 * Result is placed in surf1.
	 */

	ColorBlend(&surf1->amb, &surf2->amb, p, q);
	ColorBlend(&surf1->diff, &surf2->diff, p, q);
	ColorBlend(&surf1->spec, &surf2->spec, p, q);

	surf1->coef = blend(surf1->coef, surf2->coef, p, q);
	surf1->refl = blend(surf1->refl, surf2->refl, p, q);
	surf1->transp = blend(surf1->transp, surf2->transp, p, q);
	surf1->kref = blend(surf1->kref, surf2->kref, p, q);
	surf1->atmos = (Atmosphere *)NULL;	/* Punt */
}

/*
 * Blend two colors.  Result is placed in color1.
 */
void
ColorBlend(color1, color2, p, q)
Color *color1, *color2;
Float p, q;
{
	color1->r = blend(color1->r, color2->r, p, q);
	color1->g = blend(color1->g, color2->g, p, q);
	color1->b = blend(color1->b, color2->b, p, q);
}

SurfList *
SurfPop(list)
SurfList *list;
{
	SurfList *stmp = list->next;

	free((voidstar)list);
	return stmp;
}

SurfList *
SurfPush(surf, list)
Surface *surf;
SurfList *list;
{
	SurfList *stmp;

	stmp = (SurfList *)Malloc(sizeof(SurfList));
	stmp->surf = surf;
	stmp->next = list;
	return stmp;
}
