/*
Copyright (C) 1999-2006 Id Software, Inc. and contributors.
For a list of contributors, see the accompanying CONTRIBUTORS file.

This file is part of GtkRadiant.

GtkRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

GtkRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "qbsp.h"

int		nummiptex;
textureref_t	textureref[MAX_MAP_TEXTURES];

//==========================================================================


int	FindMiptex (char *name)
{
	int		i;
	char	path[1024];
	miptex_t	*mt;
	miptex_m8_t	*mt_m8;
	miptex_m32_t	*mt_m32;

	for (i=0 ; i<nummiptex ; i++)
		if (!strcmp (name, textureref[i].name))
		{
			return i;
		}
	if (nummiptex == MAX_MAP_TEXTURES)
		Error ("MAX_MAP_TEXTURES");
	strcpy (textureref[i].name, name);

	// load the miptex to get the flags and values
	if ( !strcmp( game, "heretic2" ) )
	{
		sprintf (path, "%stextures/%s.m32", gamedir, name);
		if (TryLoadFile (path, (void **)&mt_m32) != -1)
		{
			textureref[i].value = LittleLong (mt_m32->value);
			textureref[i].flags = LittleLong (mt_m32->flags);
			textureref[i].contents = LittleLong (mt_m32->contents);
			strcpy (textureref[i].animname, mt_m32->animname);
			free (mt_m32);
		}
		else
			sprintf (path, "%stextures/%s.m8", gamedir, name);
		
		if (TryLoadFile (path, (void **)&mt_m8) != -1)
		{
			textureref[i].value = LittleLong (mt_m8->value);
			textureref[i].flags = LittleLong (mt_m8->flags);
			textureref[i].contents = LittleLong (mt_m8->contents);
			strcpy (textureref[i].animname, mt_m8->animname);
			free (mt_m8);
		}
	}
	else
	{
	sprintf (path, "%stextures/%s.wal", gamedir, name);
		if (TryLoadFile (path, (void **)&mt) != -1)
		{
			textureref[i].value = LittleLong (mt->value);
			textureref[i].flags = LittleLong (mt->flags);
			textureref[i].contents = LittleLong (mt->contents);
			strcpy (textureref[i].animname, mt->animname);
			free (mt);
		}
	}
	
	nummiptex++;

	if (textureref[i].animname[0])
		FindMiptex (textureref[i].animname);

	return i;
}


/*
==================
textureAxisFromPlane
==================
*/
vec3_t	baseaxis[18] =
{
{0,0,1}, {1,0,0}, {0,-1,0},			// floor
{0,0,-1}, {1,0,0}, {0,-1,0},		// ceiling
{1,0,0}, {0,1,0}, {0,0,-1},			// west wall
{-1,0,0}, {0,1,0}, {0,0,-1},		// east wall
{0,1,0}, {1,0,0}, {0,0,-1},			// south wall
{0,-1,0}, {1,0,0}, {0,0,-1}			// north wall
};

void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
{
	int		bestaxis;
	vec_t	dot,best;
	int		i;
	
	best = 0;
	bestaxis = 0;
	
	for (i=0 ; i<6 ; i++)
	{
		dot = DotProduct (pln->normal, baseaxis[i*3]);
		if (dot > best)
		{
			best = dot;
			bestaxis = i;
		}
	}
	
	VectorCopy (baseaxis[bestaxis*3+1], xv);
	VectorCopy (baseaxis[bestaxis*3+2], yv);
}




int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin)
{
	vec3_t	vecs[2];
	int		sv, tv;
	vec_t	ang, sinv, cosv;
	vec_t	ns, nt;
	texinfo_t	tx, *tc;
	int		i, j, k;
	float	shift[2];
	brush_texture_t		anim;
	int				mt;

	if (!bt->name[0])
		return 0;

	memset (&tx, 0, sizeof(tx));
	strcpy (tx.texture, bt->name);

	TextureAxisFromPlane(plane, vecs[0], vecs[1]);

	shift[0] = DotProduct (origin, vecs[0]);
	shift[1] = DotProduct (origin, vecs[1]);

	if (!bt->scale[0])
		bt->scale[0] = 1;
	if (!bt->scale[1])
		bt->scale[1] = 1;


// rotate axis
	if (bt->rotate == 0)
		{ sinv = 0 ; cosv = 1; }
	else if (bt->rotate == 90)
		{ sinv = 1 ; cosv = 0; }
	else if (bt->rotate == 180)
		{ sinv = 0 ; cosv = -1; }
	else if (bt->rotate == 270)
		{ sinv = -1 ; cosv = 0; }
	else
	{	
		ang = bt->rotate / 180 * Q_PI;
		sinv = sin(ang);
		cosv = cos(ang);
	}

	if (vecs[0][0])
		sv = 0;
	else if (vecs[0][1])
		sv = 1;
	else
		sv = 2;
				
	if (vecs[1][0])
		tv = 0;
	else if (vecs[1][1])
		tv = 1;
	else
		tv = 2;
					
	for (i=0 ; i<2 ; i++)
	{
		ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
		nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
		vecs[i][sv] = ns;
		vecs[i][tv] = nt;
	}

	for (i=0 ; i<2 ; i++)
		for (j=0 ; j<3 ; j++)
			tx.vecs[i][j] = vecs[i][j] / bt->scale[i];

	tx.vecs[0][3] = bt->shift[0] + shift[0];
	tx.vecs[1][3] = bt->shift[1] + shift[1];
	tx.flags = bt->flags;
	tx.value = bt->value;

	//
	// find the texinfo
	//
	tc = texinfo;
	for (i=0 ; i<numtexinfo ; i++, tc++)
	{
		if (tc->flags != tx.flags)
			continue;
		if (tc->value != tx.value)
			continue;
		for (j=0 ; j<2 ; j++)
		{
			if (strcmp (tc->texture, tx.texture))
				goto skip;
			for (k=0 ; k<4 ; k++)
			{
				if (tc->vecs[j][k] != tx.vecs[j][k])
					goto skip;
			}
		}
		return i;
skip:;
	}
	*tc = tx;
	numtexinfo++;

	// load the next animation
	mt = FindMiptex (bt->name);
	if (textureref[mt].animname[0])
	{
		anim = *bt;
		strcpy (anim.name, textureref[mt].animname);
		tc->nexttexinfo = TexinfoForBrushTexture (plane, &anim, origin);
	}
	else
		tc->nexttexinfo = -1;


	return i;
}
