#ifndef lint
static char *sccsid = "@(#)world.c	1.3 (Steve Hill) 5/23/90";
#endif

/* world.c
 *
 * Functions for manipulating the world.  Allows the
 * setting of parameters such as view position, view direction,
 * ambient lighting level etc.
 */

#include <stdio.h>

#include "basetype.h"
#include "error.h"
#include "cartesian.h"
#include "malloc.h"
#include "matrix.h"
#include "point.h"
#include "colour.h"
#include "vector.h"
#include "indexlist.h"
#include "ray.h"
#include "light.h"
#include "quadric.h"
#include "surface.h"
#include "bitmap.h"
#include "pattern.h"
#include "solid.h"
#include "bbox.h"
#include "world.h"

point_t
default_view_point =
{
	REAL_ZERO,
	REAL_ZERO,
	REAL_ZERO
};

vector_t
default_view_vector =
{
	REAL_ZERO,
	REAL_ZERO,
	REAL_ONE
};

vector_t
default_vert_vector =
{
	REAL_ZERO,
	REAL_ONE,
	REAL_ZERO
};

real_t	default_view_plane = REAL_ONE;

int	default_pixels_x = DEFAULT_PIXELS_X,
	default_pixels_y = DEFAULT_PIXELS_Y;

real_t	default_view_x   = DEFAULT_VIEW_X,
	default_view_y   = DEFAULT_VIEW_Y;

colour_t
default_ambient_light =
{
	REAL_ONE,
	REAL_ONE,
	REAL_ONE
};

colour_t
default_sky =
{
	(real_t) 0.0,
	(real_t) 0.0,
	(real_t) 0.5
};

FILE	*default_file = stdout;

world_t *
World()
{
	world_t	*world;

	world = (world_t *) malloc(sizeof(world_t));

	if (world == WorldNull)
		FatalError(__FILE__, __LINE__, "World: Out of memory");

	world->view_point  = PointCopy(&default_view_point);
	world->view_vector = VectorCopy(&default_view_vector);
	world->vert_vector = VectorCopy(&default_vert_vector);
	world->view_plane  = default_view_plane;
	world->pixels_x    = default_pixels_x;
	world->pixels_y    = default_pixels_y;
	world->start_x     = 0;
	world->start_y     = 0;
	world->stop_x      = world->pixels_x - 1;
	world->stop_y      = world->pixels_y - 1;
	world->view_x      = default_view_x;
	world->view_y      = default_view_y;
	world->ambient     = ColourCopy(&default_ambient_light);
	world->sky	   = ColourCopy(&default_sky);

	world->report_progress = TRUE;
	world->file        = default_file;
	world->file_name   = NULL;

	world->solid	   = SolidNull;
	world->lights	   = LightListNull;

	return(world);
}


void
WorldPrint(file, world)
FILE	*file;
world_t	*world;
{
	PointPrint(file, world->view_point);
	VectorPrint(file, world->view_vector);
	VectorPrint(file, world->vert_vector);
	VectorPrint(file, world->horz_vector);
	fprintf(file, "%f %f %f ", world->view_x, world->view_y,
				   world->view_plane);
	fprintf(file, "%d %d ", world->pixels_x, world->pixels_y);
	ColourPrint(file, world->ambient);
	fprintf(file, "%x %s ", world->file, world->file_name);
	SolidPrint(file, world->solid);
	LightListPrint(file, world->lights);
}


/* CameraVectors
 *
 * Generates the vector corresponding to horizontal from the view vector
 * (the way that the camera is pointing), and the vertical (up) vector.
 * It adjusts the vertical vector so that is is at right angles to the
 * view vector (if this were not already so).
 */

void
CameraVectors(world)
world_t	*world;
{
	world->horz_vector = VectorCross(VectorNull, world->vert_vector,
						     world->view_vector);
	(void) VectorNormalise(world->horz_vector, world->horz_vector);
	(void) VectorCross(world->vert_vector, world->view_vector,
					       world->horz_vector);
	(void) VectorNormalise(world->vert_vector, world->vert_vector);
	(void) VectorNormalise(world->view_vector, world->view_vector);
}


void
WorldPplane(world, x, y, d)
world_t	*world;
real_t	x, y, d;
{
	world->view_x = x;
	world->view_y = y;
	world->view_plane = d;
}

void
WorldResolution(world, x, y)
world_t	*world;
int	x, y;
{
	world->pixels_x = x;
	world->stop_x = x - 1;
	world->pixels_y = y;
	world->stop_y = y - 1;
}

void
WorldLocation(world, point)
world_t	*world;
point_t	*point;
{
	PointFree(world->view_point);
	world->view_point = point;
}

void
WorldLook(world, vector)
world_t		*world;
vector_t	*vector;
{
	VectorFree(world->view_vector);
	world->view_vector = vector;
}

void
WorldUp(world, vector)
world_t		*world;
vector_t	*vector;
{
	VectorFree(world->vert_vector);
	world->vert_vector = vector;
}

void
WorldLight(world, light)
world_t	*world;
light_t	*light;
{
	world->lights = LightListCons(light, world->lights);
}

void
WorldAmbient(world, colour)
world_t		*world;
colour_t	*colour;
{
	ColourFree(world->ambient);
	world->ambient = colour;
}

void
WorldSolid(world, solid)
world_t	*world;
solid_t	*solid;
{
	world->solid = SolidBbox(solid);
}

void
WorldFileName(world, file_name)
world_t	*world;
char	*file_name;
{
	world->file_name = file_name;
}

void
WorldSky(world, sky_colour)
world_t		*world;
colour_t	*sky_colour;
{
	if (world->sky != ColourNull)
		ColourFree(world->sky);

	world->sky = sky_colour;
}
