#ifndef lint
static char *sccsid = "%W% (Steve Hill) %G%";
#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"
#include "rasterfile.h"


/* BitMapFunction
 *
 * Deals with bitmaps.
 */

static
bitmap_t *
BitMapped(x_size, z_size, surface, bm)
real_t		x_size, z_size;
surface_t	*surface;
bm_t		*bm;
{
	bitmap_t	*bitmap;

	bitmap = (bitmap_t *) malloc(sizeof(bitmap_t));

	bitmap->x_size = x_size;
	bitmap->z_size = z_size;
	bitmap->surface1 = surface;
	bitmap->surface2 = SurfaceCopy(&default_surface);
	bitmap->bm = bm;

	return(bitmap);
}

static
void
BitMapFunction(solid, pattern)
solid_t 	*solid;
pattern_t	*pattern;
{
	description_t	*description;
	bitmap_t	*bitmap;
	bm_t		*bm;
	int		x, z;
	point_t		*point;

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

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

	bitmap = description->body.bitmap;
	bm = bitmap->bm;

	x = RealAbs((point->x / bitmap->x_size) * bm->xres);
	z = RealAbs((point->z / bitmap->z_size) * bm->zres);

	x = x % bm->xres;
	z = z % bm->zres;

	/* fprintf(stderr, "xres = %d, x = %d\n", bm->xres, x);
	fprintf(stderr, "zres = %d, z = %d\n", bm->zres, z); */

	if (bm->map_type == RT_STANDARD)
	{
		int	pix = (unsigned char) (bm->data)[(int) (x + z * ((bm->xres + 1) / 2 * 2))];

		bitmap->surface2->diffuse->r
			= bitmap->surface1->diffuse->r * (unsigned char) (bm->red)[pix] / 255;
		bitmap->surface2->diffuse->g
			= bitmap->surface1->diffuse->g * (unsigned char) (bm->green)[pix] / 255;
		bitmap->surface2->diffuse->b
			= bitmap->surface1->diffuse->b * (unsigned char) (bm->blue)[pix] / 255;
	}
	else
	{
		int	pix = ((unsigned char) (bm->data)[(int) (x / 8 + z * ((bm->xres + 15) / 16 * 2))]) & (128 >> ((int) x % 8));
		pix = (pix == 0) ? 0 : 1;

		bitmap->surface2->diffuse->r
			= bitmap->surface1->diffuse->r * pix;
		bitmap->surface2->diffuse->g
			= bitmap->surface1->diffuse->g * pix;
		bitmap->surface2->diffuse->b
			= bitmap->surface1->diffuse->b * pix;
	}
	solid->body.atom.surface = bitmap->surface2;
}
 
pattern_t *
BitMap(x_res, z_res, surface1, bm)
real_t		x_res, z_res;
surface_t	*surface1;
bm_t		*bm;
{
	description_t	*description;
	bitmap_t	*bitmap;

	bitmap = BitMapped(x_res, z_res, surface1, bm);
	description = Description(BITMAP, (address_t) bitmap);

	return(Pattern(description, BitMapFunction));
}
