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

/* patterns.c
 *
 * This module contains a number of pre-defined patterns for
 * use with the ray tracer.
 */

#include <stdio.h>
#include <math.h>

#include "basetype.h"
#include "cartesian.h"
#include "vector.h"
#include "matrix.h"
#include "point.h"
#include "indexlist.h"
#include "ray.h"
#include "quadric.h"
#include "list.h"
#include "colour.h"
#include "surface.h"
#include "bitmap.h"
#include "pattern.h"
#include "solid.h"
#include "bbox.h"
#include "patterns.h"


/* Chequered
 *
 * Produces a pattern of blocks.  If this pattern is combined with a
 * plane, then it gives the familiar chequerboard pattern beloved
 * of ray tracers.
 */

static
void
ChequeFunction(solid, pattern)
solid_t 	*solid;
pattern_t	*pattern;
{
	description_t	*description;
	chequered_t	*chequered;
	real_t		ix, iy, iz;
	point_t		*point;

	description = pattern->description;
	point       = pattern->point;

	if (description->sort != CHEQUERED)
		FatalError(__FILE__, __LINE__, "ChequeredFunction: wrong sort");

	chequered = description->body.chequered;

	ix = point->x / chequered->x_res;
	iy = point->y / chequered->y_res;
	iz = point->z / chequered->z_res;

	if (ix < 0) ix = ix - 1;
	if (iy < 0) iy = iy - 1;
	if (iz < 0) iz = iz - 1;

	if ((((int) ix + (int) iy + (int) iz) % 2) == 0)
		solid->body.atom.surface = chequered->surface1;
	else
		solid->body.atom.surface = chequered->surface2;
}
 
pattern_t *
Cheque(x_res, y_res, z_res, surface1, surface2)
real_t		x_res, y_res, z_res;
surface_t	*surface1, *surface2;
{
	description_t	*description;
	chequered_t	*chequered;

	chequered   = Chequered(x_res, y_res, z_res, surface1, surface2);
	description = Description(CHEQUERED, (address_t) chequered);

	return(Pattern(description, ChequeFunction));
}


/* Layered
 *
 */

static
void
LayerFunction(solid, pattern)
solid_t 	*solid;
pattern_t	*pattern;
{
	description_t	*description;
	layered_t	*layered;
	real_t		r;
	point_t		*point;

	description = pattern->description;
	point       = pattern->point;

	if (description->sort != LAYERED)
		FatalError(__FILE__, __LINE__, "LayeredFunction: wrong sort");

	layered = description->body.layered;

	switch (layered->axis)
	{
	case X_AXIS:
		r = point->x / layered->res;
		break;

	case Y_AXIS:
		r = point->y / layered->res;
		break;

	case Z_AXIS:
		r = point->z / layered->res;
		break;

	default:
		FatalError(__FILE__, __LINE__, "LayeredFunction: bad axis");
	}

	if (r < 0) r = r - 1;

	if ((((int) r) % 2) == 0)
		solid->body.atom.surface = layered->surface1;
	else
		solid->body.atom.surface = layered->surface2;
}
 
pattern_t *
Layer(res, axis, surface1, surface2)
real_t		res;
axis_t		axis;
surface_t	*surface1, *surface2;
{
	description_t	*description;
	layered_t	*layered;

	layered = Layered(res, axis, surface1, surface2);
	description = Description(LAYERED, (address_t) layered);

	return(Pattern(description, LayerFunction));
}
