/* overlay.c */
/* Score overlay functions go in here */
/* Each overlay is created and held inside a structure */

#include "gameinc.h"


static br_token_value blend_tokens[] =
	{
    BRT_BLEND_B,BR_TRUE,
//	BRT_OPACITY_F, 160.0,		/* BRender float opacity is knackered, or something */
	BRT_OPACITY_X, 0xa00000,	/* i.e. 160 in fixed point - this is hideous */
    0
    };

p_O_Overlay Overlay_Init(br_pixelmap *overlay)
{
	p_O_Overlay this;
	br_actor *world, *camera, *copy;
	br_material *material;
	br_model *thismodel;
	int width,height;

	if (overlay == NULL)
	{
		fatal("NULL overlay pointer passed in!!");
	}

	width = (int)(overlay->width *1.5F);
	height = (int)(overlay->height *1.5F);
//	width = overlay->width;
//	height = overlay->height;
	this = calloc(1,sizeof(struct s_O_Overlay));

	if (this == NULL)
	{
		fatal("Not enough memory for overlay structure!!");
	}

// FIXME Each overlay has its own world, camera, material etc.
// This is bad, remember to pull out the reused bits and just hold
// a different material and/or model for each one.
	/* Setup the mini-BRender world with materials, models and cameras. */
	/* Allocate material with texture information */
	material = BrMaterialAllocate("ooverlaymat");
	material->flags = BR_MATF_PRELIT | BR_MATF_MAP_INTERPOLATION | BR_MATF_PERSPECTIVE
				| BR_MATF_ALWAYS_VISIBLE | BR_MATF_FORCE_FRONT | BR_MATF_SMOOTH;
	material->colour_map = overlay;
	material->colour = BR_COLOUR_RGB(255,255,255);
	material->extra_prim = blend_tokens;
	BrMaterialAdd(material);

	/* Create a model with two faces, two texture mapped triangles */
	thismodel = BrModelAllocate("ooverlaymod",4,2);
	thismodel->vertices[0].p.v[0]=BR_SCALAR(0);
	thismodel->vertices[0].p.v[1]=BR_SCALAR(-height);
	thismodel->vertices[0].p.v[2]=BR_SCALAR(0.0);
	thismodel->vertices[0].red = 255;
	thismodel->vertices[0].grn = 255;
	thismodel->vertices[0].blu = 255;
	thismodel->vertices[0].map.v[0]=BR_SCALAR(0.0);
	thismodel->vertices[0].map.v[1]=BR_SCALAR(1.0);

		
	thismodel->vertices[1].p.v[0]=BR_SCALAR(width);
	thismodel->vertices[1].p.v[1]=BR_SCALAR(-height);
	thismodel->vertices[1].p.v[2]=BR_SCALAR(0.0);
	thismodel->vertices[1].red = 255;
	thismodel->vertices[1].grn = 255;
	thismodel->vertices[1].blu = 255;
	thismodel->vertices[1].map.v[0]=BR_SCALAR(1.0);
	thismodel->vertices[1].map.v[1]=BR_SCALAR(1.0);

	thismodel->vertices[2].p.v[0]=BR_SCALAR(width);
	thismodel->vertices[2].p.v[1]=BR_SCALAR(0);
	thismodel->vertices[2].p.v[2]=BR_SCALAR(0.0);
	thismodel->vertices[2].red = 255;
	thismodel->vertices[2].grn = 255;
	thismodel->vertices[2].blu = 255;
	thismodel->vertices[2].map.v[0]=BR_SCALAR(1.0);
	thismodel->vertices[2].map.v[1]=BR_SCALAR(0.0);

	thismodel->vertices[3].p.v[0]=BR_SCALAR(0);
	thismodel->vertices[3].p.v[1]=BR_SCALAR(0);
	thismodel->vertices[3].p.v[2]=BR_SCALAR(0.0);
	thismodel->vertices[3].red = 255;
	thismodel->vertices[3].grn = 255;
	thismodel->vertices[3].blu = 255;
	thismodel->vertices[3].map.v[0]=BR_SCALAR(0.0);
	thismodel->vertices[3].map.v[1]=BR_SCALAR(0.0);


	thismodel->faces[0].vertices[0]=0;
	thismodel->faces[0].vertices[1]=1;
	thismodel->faces[0].vertices[2]=2;
	thismodel->faces[0].material=material;

	thismodel->faces[1].vertices[0]=0;
	thismodel->faces[1].vertices[1]=2;
	thismodel->faces[1].vertices[2]=3;
	thismodel->faces[1].material=material;

	thismodel->flags=BR_MODF_KEEP_ORIGINAL;

	/* Add model to registry */
	BrModelAdd(thismodel);
	BrModelUpdate(thismodel,BR_MODU_ALL);

	/* Allocate a mini hierarchy of actors and their models */
	world = BrActorAllocate(BR_ACTOR_NONE,NULL);

	copy = BrActorAdd(world,BrActorAllocate(BR_ACTOR_MODEL,NULL));

	copy->model = thismodel;

	/* Allocate a camera that looks at the mini model */
	camera = BrActorAllocate(BR_ACTOR_CAMERA, NULL);
	camera->identifier = "ocameraoverlay";
	((br_camera *) camera->type_data)->type = BR_CAMERA_PERSPECTIVE;
	((br_camera *) camera->type_data)->field_of_view = BR_ANGLE_DEG(45.0);
	((br_camera *) camera->type_data)->hither_z = BR_SCALAR(2.0);
	((br_camera *) camera->type_data)->yon_z = BR_SCALAR(20000.0);
	((br_camera *) camera->type_data)->aspect = BR_SCALAR(1.6);
	camera->t.type = BR_TRANSFORM_MATRIX34;
	BrActorAdd(world, camera);

	this->world = world;
	this->camera = camera;
	this->copy = copy;
	this->material = material;
	this->thismodel = thismodel;

	return this;
}


void Overlay_DisplayOverlay(br_pixelmap *screen,br_pixelmap *depth,p_O_Overlay this)
{

	br_actor *world, *camera, *copy;
	br_material *material;
	br_model *thismodel;
	int xpos,ypos;

	world = this->world;
	camera = this->camera;
	copy = this->copy;
	material = this->material;
	thismodel = this->thismodel;
	xpos = this->xpos;
	ypos = this->ypos;

	/* Move camera depending on how many pixels of the screen should be displayed */
	BrMatrix34Translate(&camera->t.t.mat, BR_SCALAR(-424.0F*(((float)(xpos-320))/320.0)), BR_SCALAR(264.0F*(((float)(ypos-240))/240.0)), BR_SCALAR(640));

	/* Fill depth buffer and render */
//	BrPixelmapFill(depth, 0xffffffff);
	BrZbSceneRender(world, camera, screen, depth);

}



