//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright © 1999 - 2003, Okan Arikan
//
// Contact: okan@cs.berkeley.edu
//
// This library 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 library 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 library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	opengl.cpp
//  Classes				:	COpenGL
//  Description			:	The opengl hider
//
////////////////////////////////////////////////////////////////////////
#include "opengl.h"
#include "renderer.h"

///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	COpenGL
// Description			:	Ctor
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
COpenGL::COpenGL(COptions *o,CXform *a,SOCKET s) : CShadingContext(o,a,s,HIDER_NODISPLAY | HIDER_RGBAZ_ONLY) {
	char	modulePath[OS_MAX_PATH_LENGTH];

	if (currentRenderer->locateFileEx(modulePath,"opengl",osModuleExtension,proceduralPath) == TRUE) {
		handle	=	osLoadModule(modulePath);

		if (handle != NULL) {
			glInit		=	(openglInitFun)		osResolve(handle,"openglInit");
			glTini		=	(openglTiniFun)		osResolve(handle,"openglTini");
			glDrawGrid	=	(openglDrawGridFun)	osResolve(handle,"openglDrawGrid");
		}
	}


	objects	=	new CArray<CObject *>;
}

///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	~COpenGL
// Description			:	Dtor
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
COpenGL::~COpenGL() {
	if (handle != NULL)	osUnloadModule(handle);

	delete objects;
}

///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	renderFrame
// Description			:	RTender the frame
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
void	COpenGL::renderFrame() {

	if (glInit != NULL)	{
		THWCamera	camera;
		int			i;
		int			numObjects	=	objects->numItems;
		CObject		**obj		=	objects->array;

		camera.xres			=	xres;
		camera.yres			=	yres;
		camera.clipMin		=	max(0,worldBmin[COMP_Z]);
		camera.clipMax		=	max(0,worldBmax[COMP_Z]);
		camera.left			=	pixelLeft;
		camera.right		=	pixelRight;
		camera.top			=	pixelTop;
		camera.bottom		=	pixelBottom;
		camera.imagePlane	=	imagePlane;
		camera.perspective	=	(projection == OPTIONS_PROJECTION_PERSPECTIVE ? TRUE : FALSE);
	
		camera.xres	=	xres;

		glInit(&camera);

		for (i=0;i<numObjects;i++) {
			obj[i]->dice(this);
			obj[i]->detach();
		}

		if (glTini != NULL)	glTini();
	}
}



///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	drawObject
// Description			:	Draw an object
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
void		COpenGL::drawObject(CObject *object,const float *bmin,const float *bmax) {
	if (inFrustrum(bmin,bmax)) {
		object->dice(this);
	}
}

///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	renderFrame
// Description			:	RTender the frame
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
void		COpenGL::drawGrid(CSurface *surface,int nu,int nv,float umin,float umax,float vmin,float vmax) {
	if (glDrawGrid != NULL) {
		// Render the thing
		const	float	ustart		=	umin;
		const	float	vstart		=	vmin;
		const	int		udiv		=	nu - 1;
		const	int		vdiv		=	nv - 1;
		const	float	ustep		=	(umax - ustart) / (float) udiv;
		const	float	vstep		=	(vmax - vstart) / (float) vdiv;
		float			**varying	=	currentShadingState->varying;
		float			*uv			=	varying[VARIABLE_U];
		float			*vv			=	varying[VARIABLE_V];
		float			*timev		=	varying[VARIABLE_TIME];
		float			u,v;
		int				up,vp;
		int				k;

		for (vp=0,v=vstart,k=0;vp<(vdiv+1);vp++,v+=vstep) {
			for (up=0,u=ustart;up<(udiv+1);up++,u+=ustep,k++) {
				uv[k]		=	u;
				vv[k]		=	v;
				timev[k]	=	0;
			}
		}

		shade(surface,udiv+1,vdiv+1,2,PARAMETER_P | PARAMETER_CI);

		glDrawGrid(nu,nv,varying[VARIABLE_P],varying[VARIABLE_CI]);
	}
}

///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	renderFrame
// Description			:	RTender the frame
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
void		COpenGL::drawRibbon(CSurface *surface,int nv,float vmin,float vmax) {
}

///////////////////////////////////////////////////////////////////////
// Class				:	COpenGL
// Method				:	renderFrame
// Description			:	RTender the frame
// Return Value			:	-
// Comments				:
// Date last edited		:	9/15/2003
void		COpenGL::drawPoints(CSurface *surface,int np) {
}
