/*
Copyright (C) 1996-1997 Id Software, Inc.

This program 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.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// FIXME: add this to rscript + fix skybox problem
// Modified for use with tomazquake by BramBo

#include "quakedef.h"

// glmsurface_t == msurface_t


// bloody mirrors
qboolean mirror;
mplane_t *mirror_plane;
cvar_t r_mirroralpha = {"r_mirroralpha","1", true};
msurface_t *mirrorchain = NULL;
qboolean mirror_render;	// true when reflections are being rendered

void Mirror_Scale (void)
{
	if (mirror_plane->normal[2])
		glScalef (1, -1, 1);
	else glScalef (-1, 1, 1);

	glCullFace(GL_BACK);
}


void Mirror_Clear (void)
{
	if (gl_clear.value)
		glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	else
		glClear (GL_DEPTH_BUFFER_BIT);

	gldepthmin = 0;
	gldepthmax = 0.5;
	glDepthFunc (GL_LEQUAL);
}

/*
=============
R_Mirror

  code written by MH - http://mhquake.quakesrc.org/
=============
*/
extern cvar_t gl_multitexture;
float r_base_world_matrix[16];
void R_RenderScene (void);

void R_Mirror (void)
{
	float d;
	msurface_t *s;
	entity_t *ent;
	float mirror_alpha;
	glpoly_t	*p;
	float		*v;
	int			i;


	// these should stay the same for all mirror planes
	vec3_t oldvieworg;
	vec3_t oldviewangles;
	vec3_t oldvpn;


	// don't have infinite reflections if 2 mirrors are facing each other (looks ugly but
	// better than hanging the engine)
	mirror_render = true;

	ent = &cl_entities[cl.viewentity];

	if (cl_numvisedicts < MAX_VISEDICTS)
	{
		cl_visedicts[cl_numvisedicts] = ent;
		cl_numvisedicts++;
	}

	memcpy (r_base_world_matrix, r_world_matrix, sizeof (r_base_world_matrix));

	oldvieworg[0] = r_refdef.vieworg[0];
	oldvieworg[1] = r_refdef.vieworg[1];
	oldvieworg[2] = r_refdef.vieworg[2];

	oldviewangles[0] = r_refdef.viewangles[0];
	oldviewangles[1] = r_refdef.viewangles[1];
	oldviewangles[2] = r_refdef.viewangles[2];

	oldvpn[0] = vpn[0];
	oldvpn[1] = vpn[1];
	oldvpn[2] = vpn[2];

	// r_mirroralpha values of more than about 0.65 don't really look well or have any effect
	mirror_alpha = (r_mirroralpha.value / 1.5);

	for (s = mirrorchain; s; s = s->texturechain)
	{
		mirror_plane = s->plane;

		d = DotProduct (oldvieworg, mirror_plane->normal) - mirror_plane->dist;
		VectorMA (oldvieworg, -2 * d, mirror_plane->normal, r_refdef.vieworg);

		d = DotProduct (oldvpn, mirror_plane->normal);
		VectorMA (oldvpn, -2 * d, mirror_plane->normal, vpn);

		r_refdef.viewangles[0] = -asin (vpn[2]) / M_PI * 180;
		r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0]) / M_PI * 180;
		r_refdef.viewangles[2] = -oldviewangles[2];

		gldepthmin = 0.5;
		gldepthmax = 1;
		glDepthRange (gldepthmin, gldepthmax);
		glDepthFunc (GL_LEQUAL);

		// everything to do with the render has been moved into r_renderscene, so that the
		// full render reflects properly in the skybox...
		R_RenderScene ();

		gldepthmin = 0;
		gldepthmax = 0.5;
		glDepthRange (gldepthmin, gldepthmax);
		glDepthFunc (GL_LEQUAL);
		glMatrixMode (GL_PROJECTION);

		if (mirror_plane->normal[2])
			glScalef (1, -1, 1);
		else
			glScalef (-1, 1, 1);

		glCullFace (GL_FRONT);
		glMatrixMode (GL_MODELVIEW);
		glLoadMatrixf (r_base_world_matrix);

		glColor4f (1, 1, 1, mirror_alpha);

		glBindTexture (GL_TEXTURE_2D, s->texinfo->texture->gl_texturenum);

		p = s->polys;
		v = p->verts[0];

		glBegin (GL_POLYGON);

		for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
		{
			glTexCoord2fv (&v[3]);
			glVertex3fv (v);
		}

		glEnd ();
		glColor4f (1, 1, 1, 1);
	}

	mirrorchain = NULL;
	mirror = false;
	mirror_render = false;
}


