//-----------------------------------------------------------------------------
//
//  $Logfile:: /Source/gl_console3d.c                                         $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 5:16 PM                                               $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION: 3D Game console
//

#include "gl_local.h"

// Global console information.
conInfo_t consoleInfo;

void R_DrawConsole(msurface_t *psurf, int num_surfaces, vec3_t surf_origin)
{
	int j;
	float mins, mint, maxs, maxt;
	vec3_t offset_origin, diff;
	float dist, delta;
	qboolean restore_multitexture = false;

	// Set up a coordinate system based on this
	// entity's surface.
	if (num_surfaces > 0)
	{	/* Anything to perform? */
		do
		{
			mtexinfo_t *TexPtr;
			TexPtr = psurf->texinfo;
			if (TexPtr)
			{
				if (TexPtr->flags & SURF_CONSOLE)
				{
					vec3_t origin,prevpoint,nextpoint;
					glpoly_t *PolyPtr;

					// do not use VectorClear here: gcc may mess things up
					VectorCopy(vec3_origin, origin);
					VectorCopy(vec3_origin, nextpoint);
					VectorCopy(vec3_origin, prevpoint);
					mins = 99999;
					mint = 99999;
					maxs = -99999;
					maxt = -99999;
					PolyPtr = psurf->polys;
					// Find texture coordinate extents
					for (j = 0; j < PolyPtr->numverts; j++)
					{
						float s,t;

						s = PolyPtr->verts[j][3] - psurf->texturemins[0]/TexPtr->image->width;
						t = PolyPtr->verts[j][4] - psurf->texturemins[1]/TexPtr->image->height;
						mins = __min(mins,s);
						mint = __min(mint,t);
						maxs = __max(maxs,s);
						maxt = __max(maxt,t);
					}

					// Define the coordinate system of this surface.
					// Origin is defined at MINS,MAXT (0,1)
					for (j = 0; j < PolyPtr->numverts; j++)
					{
						float s, t;

						s = PolyPtr->verts[j][3] - psurf->texturemins[0]/TexPtr->image->width;
						t = PolyPtr->verts[j][4] - psurf->texturemins[1]/TexPtr->image->height;
						#if 0
						ri.Con_Printf(PRINT_DEVELOPER,
								"vert:%d x:%2.0f y:%2.0f z:%2.0f s:%f t:%f\n mins:%f mint:%f maxs:%f maxt:%f\n", j,
								PolyPtr->verts[j][0],
								PolyPtr->verts[j][1],
								PolyPtr->verts[j][2],
								s,t,mins,mint,maxs,maxt);
						#endif
						if (s == mins && t == maxt) {
							VectorCopy(PolyPtr->verts[j], origin);
						} else if (s == maxs && t == maxt) {
							VectorCopy(PolyPtr->verts[j], nextpoint);
						} else if (s == mins && t == mint) {
							VectorCopy(PolyPtr->verts[j], prevpoint);
						}
					}

					// Calculate distance from player to console surface
					VectorAdd(origin,surf_origin,offset_origin);

					if (!(TexPtr->flags & SURF_NOFILTER))
					{
						VectorSubtract(offset_origin, r_newrefdef.vieworg, diff);
						dist = DotProduct(diff, diff);
						if (dist > r_condist->value)
							return;
						// Set an appropriate alpha fade for the distance.
						if ((delta = r_condist->value - dist) < r_conthresh->value)
							consoleInfo.alpha = delta / r_conthresh->value;
						else
							consoleInfo.alpha = 1.0f;
					}
					else {
						consoleInfo.alpha = 1.0f;
					}

					// Calcluate u and v vectors
					VectorSubtract(nextpoint, origin, consoleInfo.u);
					VectorSubtract(prevpoint, origin, consoleInfo.v);

					// Get the surface normal
					VectorCopy(psurf->plane->normal, consoleInfo.n);
					if (psurf->flags & SURF_PLANEBACK) {
						VectorNegate(consoleInfo.n, consoleInfo.n);
					}

					// Translate to the origin of this surface.
					qglPushMatrix();
					qglTranslatef(origin[0], origin[1], origin[2]);
					VectorCopy(origin, consoleInfo.origin);

					// Offset from the surface to avoid z-aliasing.
					{
						vec3_t offset;
						VectorScale(consoleInfo.n, r_conoffset->value, offset);
						qglTranslatef(offset[0], offset[1], offset[2]);
					}

					// Calculate the width and height of this surface.
					consoleInfo.surface_width  = VectorNormalize(consoleInfo.u);
					consoleInfo.surface_height = VectorNormalize(consoleInfo.v);

					if (r_multitexture_enabled) {
						restore_multitexture = true;
						GL_EnableMultitexture(false);
					}

					GL_TexEnv(GL_MODULATE);
					qglEnable(GL_BLEND);
					qglEnable(GL_ALPHA_TEST);
					qglDisable(GL_CULL_FACE);
					qglDepthMask(0);

					// Callback to the client to process this console
					ri.CONSOLE_Process(TexPtr->surf->groupname);

					GL_TexEnv(GL_REPLACE);
					qglDisable(GL_BLEND);
					qglDisable(GL_ALPHA_TEST);
					qglEnable(GL_CULL_FACE);
					qglDepthMask(1);

					if (restore_multitexture) {
						GL_EnableMultitexture(true);
					}
					qglPopMatrix();
				}
			}
			++psurf;
		} while (--num_surfaces);
	}
}
