#include <v_lib.h>

/*
 * GL_ARB_multitexture demo
 * Brian Paul, November 1998
 * Vladimir Smirnov, November 2000
 * This program is in the public domain.
 */


#define TEXTURE_1_FILE "../media/mist.jpg"
#define TEXTURE_2_FILE "../media/rings.jpg"

#define TEX0 1
#define TEX1 2
#define TEXBOTH 3
#define ANIMATE 10
#define QUIT 100

static vboolean	Animate = true;

static GLfloat Drift = 0.0;
static GLfloat Xrot = 0, Yrot = 0, Zrot = 0.0;

static pglActiveTextureARB		glActiveTextureARB;
static pglMultiTexCoord2fARB	glMultiTexCoord2fARB;

static void Idle( void )
{
	static vec_t sc;
	if(Animate)
	{
		Drift += 0.001f;
		sc=(vec_t)((2 + sin(Drift * 10)) * 0.5f);

		glActiveTextureARB(GL_TEXTURE0_ARB);
		glMatrixMode(GL_TEXTURE);
		glLoadIdentity();
		glScalef(sc,sc,0);
		glRotatef(Drift * 90,0.0,0.0,1.0);
		glTranslatef(- sc * .5f,- sc * .5f,0);
		glMatrixMode(GL_MODELVIEW);

	}
}

static void DrawObject(void)
{
	glBegin(GL_QUADS);
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0, 0.0);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, 0.0);
		glVertex2f(-1.0, -1.0);
		
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 2.0, 0.0);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0, 0.0);
		glVertex2f(1.0, -1.0);
		
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 2.0, 2.0);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 1.0, 1.0);
		glVertex2f(1.0, 1.0);
		
		glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.0, 2.0);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.0, 1.0);
		glVertex2f(-1.0, 1.0);
	glEnd();
}

GLboolean enable0 = GL_TRUE, enable1 = GL_TRUE;

static void Display( void )
{
	glClear(GL_COLOR_BUFFER_BIT);
	glActiveTextureARB(GL_TEXTURE0_ARB);
	if(enable0)
		glEnable(GL_TEXTURE_2D);
	else
		glDisable(GL_TEXTURE_2D);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	if(enable1)
		glEnable(GL_TEXTURE_2D);
	else
		glDisable(GL_TEXTURE_2D);

	glPushMatrix();
		glRotatef(Xrot, 1.0, 0.0, 0.0);
		glRotatef(Yrot, 0.0, 1.0, 0.0);
		glRotatef(Zrot, 0.0, 0.0, 1.0);
		glScalef(5.0, 5.0, 5.0);
		glColor4f(1,1,1,1.0f);
		DrawObject();
	glPopMatrix();
	
	vglSwapBuffers();
}

static void handle_keydown(keycode_t entry)
{
	vec_t step = 3.0;
	switch(entry)
	{
		case key_up:
			Xrot += step;
			break;
		case key_down:
			Xrot -= step;
			break;
		case key_left:
			Yrot += step;
			break;
		case key_right:
			Yrot -= step;
			break;
		case key_f1:
			enable0 = (u8_t)!enable0;
			break;
		case key_f2:
			enable1 = (u8_t)!enable1;
			break;
		case key_f3:
			enable0 = GL_TRUE;
			enable1 = GL_TRUE;
			break;
		case key_f4:
			Animate = !Animate;
			break;
		case key_f10:
		case key_escape:
			vglDestroyWindow(vglGetCurrentWindow());
			exit(0);
		default:
			break;
	}
}

static u8_t luminance(u8_t *rgba)
{
	vec4_t hsv, fc;
	rgbaFromByte(fc,rgba);
	hsvFromRgb(hsv,fc);
	return CLAMP_FLOAT_TO_BYTE(hsv[2] * 256);
}

static void imgRGBAToLuminance(u8_t *pixbuf,u32_t width,u32_t height)
{
	u8_t *ptr, luma;
	u32_t i,j;
	for(i=0;i<height;i++)
	{
		ptr=pixbuf + i * (width << 2);
		for(j=0;j<width;j++,ptr+=4)
		{
			luma=luminance(ptr);
			ptr[0]=ptr[1]=ptr[2]=luma;
			ptr[3]=0;
		}
	}
}
		
static vboolean Init(void)
{
	GLuint texObj[2];
	glActiveTextureARB = NULL;
	glMultiTexCoord2fARB = NULL;
	vglQueryExtension("glActiveTextureARB",(void**)&glActiveTextureARB);
	vglQueryExtension("glMultiTexCoord2fARB",(void**)&glMultiTexCoord2fARB);
	if(!glActiveTextureARB || !glMultiTexCoord2fARB)
	{
		conlPrintf(LOG_ERROR,"GL_ARB_MULTITEXTURE not supported\n");
		return false;
	}
	/* allocate two texture objects */
	imgDefaultAlpha(200);
	/*
	texObj[0]=vglLoadTexture(TEXTURE_1_FILE,GL_LINEAR_MIPMAP_LINEAR,GL_REPEAT,GL_MODULATE);
	texObj[1]=vglLoadTexture(TEXTURE_2_FILE,GL_LINEAR_MIPMAP_LINEAR,GL_REPEAT,GL_MODULATE);
	*/
	/*
	texObj[0]=vglLoadTexture(TEXTURE_1_FILE,GL_NEAREST,GL_REPEAT,GL_MODULATE);
	texObj[1]=vglLoadTexture(TEXTURE_2_FILE,GL_NEAREST,GL_REPEAT,GL_MODULATE);
	*/

	{
		u32_t w,h;
		u8_t *pixbuf=jpgLoad(TEXTURE_1_FILE,&w,&h);
		if(!pixbuf)
			return false;
		imgRGBAToLuminance(pixbuf,w,h);
		glGenTextures(1,texObj);
		glBindTexture(GL_TEXTURE_2D,texObj[0]);
		glTexImage2D(GL_TEXTURE_2D,0,4,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,pixbuf);
		glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
		glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	}

	texObj[1]=vglLoadTexture(TEXTURE_1_FILE,GL_NEAREST,GL_REPEAT,GL_MODULATE);
	
	/* bind the texture objects to the respective texture units */
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glBindTexture(GL_TEXTURE_2D, texObj[0]);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glBindTexture(GL_TEXTURE_2D, texObj[1]);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glFrustum( -1.3333f, 1.3333f, -1.0, 1.0, 10.0, 100.0 );
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	glTranslatef( 0.0, 0.0, -70.0 );
	return true;
}

int main(void)
{
	input_record_t ev;
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	vglCreateWindow("GL_ARB_multitexture test",0,0,640,480);
	if(!Init())
	{
		vglDestroyWindow(vglGetCurrentWindow());
		return -1;
	}
	for(;;)
	{
		while(vglPending())
		{
			vglNextEvent(&ev);
			switch(ev.event)
			{
				case ev_key_down:
					handle_keydown(ev.first_code);
					break;
			}
		}
		Display();
		Idle();
		timeDelay(10); /* reduce CPU & accel overhead */
	}
	return 0;
}
