// renderextras.cpp: misc gl render code and the HUD

#include "cube.h"

void line(int x1, int y1, float z1, int x2, int y2, float z2)
{
    glBegin(GL_POLYGON);
    glVertex3f((float)x1, z1, (float)y1);
    glVertex3f((float)x1, z1, y1+0.01f);
    glVertex3f((float)x2, z2, y2+0.01f);
    glVertex3f((float)x2, z2, (float)y2);
    glEnd();
    xtraverts += 4;
};

void linestyle(float width, int r, int g, int b)
{
    glLineWidth(width);
    glColor3ub(r,g,b);
};

void box(block &b, float z1, float z2, float z3, float z4)
{
    glBegin(GL_POLYGON);
    glVertex3f((float)b.x,      z1, (float)b.y);
    glVertex3f((float)b.x+b.xs, z2, (float)b.y);
    glVertex3f((float)b.x+b.xs, z3, (float)b.y+b.ys);
    glVertex3f((float)b.x,      z4, (float)b.y+b.ys);
    glEnd();
    xtraverts += 4;
};

void dot(int x, int y, float z)
{
    const float DOF = 0.1f;
    glBegin(GL_POLYGON);
    glVertex3f(x-DOF, (float)z, y-DOF);
    glVertex3f(x+DOF, (float)z, y-DOF);
    glVertex3f(x+DOF, (float)z, y+DOF);
    glVertex3f(x-DOF, (float)z, y+DOF);
    glEnd();
    xtraverts += 4;
};

void blendbox(int x1, int y1, int x2, int y2, bool border, int tex)
{
    glDepthMask(GL_FALSE);
    glDisable(GL_TEXTURE_2D);
    if(tex>=0) 
    {
        glBindTexture(GL_TEXTURE_2D, tex);
        glEnable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);
		glColor3f(1, 1, 1);

		int texw = 512;
		int texh = texw;
		int cols = (int)((x2-x1)/texw+1);
		int rows = (int)((y2-y1)/texh+1);
		xtraverts += cols*rows*4;
			
		loopj(rows)
		{
			float ytexcut = 0.0f;
			float yboxcut = 0.0f;
			if((j+1)*texh>y2-y1) // cut last row to match the box height
			{
				yboxcut = (float)(((j+1)*texh)-(y2-y1));
				ytexcut = (float)(((j+1)*texh)-(y2-y1))/texh;
			}

			loopi(cols)
			{
				float xtexcut = 0.0f;
				float xboxcut = 0.0f;
				if((i+1)*texw>x2-x1)
				{
					xboxcut = (float)(((i+1)*texw)-(x2-x1));
					xtexcut = (float)(((i+1)*texw)-(x2-x1))/texw;
				}

				glBegin(GL_QUADS);
				glTexCoord2f(0, 0);			        glVertex2f((float)x1+texw*i, (float)y1+texh*j);
				glTexCoord2f(1-xtexcut, 0);			glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*j);
				glTexCoord2f(1-xtexcut, 1-ytexcut);	glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*(j+1)-yboxcut); 
				glTexCoord2f(0, 1-ytexcut);			glVertex2f((float)x1+texw*i, y1+texh*(j+1)-yboxcut);
				glEnd();
			}
		}
    }
    else
    {
        if(border) glColor3f(0.7f, 0.7f, 0.7f); //glColor3d(0.5, 0.3, 0.4); 
        else glColor3f(1, 1, 1);
        glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
		glBegin(GL_QUADS);
		glTexCoord2f(0, 0);	glVertex2i(x1, y1);
		glTexCoord2f(1, 0);	glVertex2i(x2, y1);
		glTexCoord2f(1, 1); glVertex2i(x2, y2); 
		glTexCoord2f(0, 1);	glVertex2i(x1, y2);
		glEnd();
		xtraverts += 4;
    };

    glDisable(GL_BLEND);
    if(tex>=0) glDisable(GL_TEXTURE_2D);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glBegin(GL_POLYGON);
    glColor3f(0.6f, 0.6f, 0.6f); //glColor3d(0.2, 0.7, 0.4); 
    glVertex2i(x1, y1);
    glVertex2i(x2, y1); 
    glVertex2i(x2, y2);
    glVertex2i(x1, y2);
    glEnd();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glEnable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);
    glDepthMask(GL_TRUE);
};

const int MAXSPHERES = 50;
struct sphere { vec o; float size, max; int type; sphere *next; };
sphere spheres[MAXSPHERES], *slist = NULL, *sempty = NULL;
bool sinit = false;

void newsphere(vec &o, float max, int type)
{
    if(!sinit)
    {
        loopi(MAXSPHERES)
        {
            spheres[i].next = sempty;
            sempty = &spheres[i];
        };
        sinit = true;
    };
    if(sempty)
    {
        sphere *p = sempty;
        sempty = p->next;
        p->o = o;
        p->max = max;
        p->size = 1;
        p->type = type;
        p->next = slist;
        slist = p;
    };
};

void renderspheres(int time)
{
    if(!slist) return;

    static Texture *exptex = NULL;
    if(!exptex) exptex = textureload("packages/misc/explosion.jpg");

    glDepthMask(GL_FALSE);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    glBindTexture(GL_TEXTURE_2D, exptex->id);  

    for(sphere *p, **pp = &slist; (p = *pp);)
    {
        glPushMatrix();
        float size = p->size/p->max;
        glColor4f(1.0f, 1.0f, 1.0f, 1.0f-size);
        glTranslatef(p->o.x, p->o.z, p->o.y);
        glRotatef(lastmillis/5.0f, 1, 1, 1);
        glScalef(p->size, p->size, p->size);
        glCallList(1);
        glScalef(0.8f, 0.8f, 0.8f);
        glCallList(1);
        glPopMatrix();
        xtraverts += 12*6*2;

        if(p->size>p->max)
        {
            *pp = p->next;
            p->next = sempty;
            sempty = p;
        }
        else
        {
            p->size += time/100.0f;   
            pp = &p->next;
        };
    };

    glDisable(GL_BLEND);
    glDepthMask(GL_TRUE);
};

string closeent;
char *entnames[] =
{
    "none?", "light", "playerstart",
    "clips", "ammobox","grenades",
    "health", "armour", "akimbo", 
    "mapmodel", "trigger", 
    "ladder", "ctf-flag", "?", "?", "?", 
};

void renderents()       // show sparkly thingies for map entities in edit mode
{
    closeent[0] = 0;
    if(!editmode) return;
    loopv(ents)
    {
        entity &e = ents[i];
        if(e.type==NOTUSED) continue;
        vec v(e.x, e.y, e.z);
        particle_splash(2, 2, 40, v);
    };
    int e = closestent();
    if(e>=0)
    {
        entity &c = ents[e];
        s_sprintf(closeent)("closest entity = %s (%d, %d, %d, %d), selection = (%d, %d)", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, getvar("selxs"), getvar("selys"));
    };
};

float cursordepth = 0.9f;
GLint viewport[4];
GLdouble mm[16], pm[16];
vec worldpos, camup, camright;

void readmatrices()
{
    glGetIntegerv(GL_VIEWPORT, viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, mm);
    glGetDoublev(GL_PROJECTION_MATRIX, pm);
    camright = vec(float(mm[0]), float(mm[4]), float(mm[8]));
    camup = vec(float(mm[1]), float(mm[5]), float(mm[9]));
};

// stupid function to cater for stupid ATI linux drivers that return incorrect depth values

float depthcorrect(float d)
{
	return (d<=1/256.0f) ? d*256 : d;
};

// find out the 3d target of the crosshair in the world easily and very acurately.
// sadly many very old cards and drivers appear to fuck up on glReadPixels() and give false
// coordinates, making shooting and such impossible.
// also hits map entities which is unwanted.
// could be replaced by a more acurate version of monster.cpp los() if needed

void readdepth(int w, int h, vec &pos)
{
    glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth);
    double worldx = 0, worldy = 0, worldz = 0;
    gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldz, &worldy);
    pos.x = (float)worldx;
    pos.y = (float)worldy;
    pos.z = (float)worldz;
};

void drawicon(float tx, float ty, int x, int y, Texture *tex = NULL, float scaling = 1/3.0f) // EDIT: AH
{
    if(!tex)
    {
        static Texture *itemstex = NULL;
        if(!itemstex) itemstex = textureload("packages/misc/items.png"); 
        tex = itemstex;
    };
    glBindTexture(GL_TEXTURE_2D, tex->id);
    glBegin(GL_QUADS);
    tx /= 192;
    ty /= 192;
    float o = scaling;
    int s = 120;
    glTexCoord2f(tx,   ty);   glVertex2i(x,   y);
    glTexCoord2f(tx+o, ty);   glVertex2i(x+s, y);
    glTexCoord2f(tx+o, ty+o); glVertex2i(x+s, y+s);
    glTexCoord2f(tx,   ty+o); glVertex2i(x,   y+s);
    glEnd();
    xtraverts += 4;
};

void invertperspective()
{
    // This only generates a valid inverse matrix for matrices generated by gluPerspective()
    GLdouble inv[16];
    memset(inv, 0, sizeof(inv));

    inv[0*4+0] = 1.0/pm[0*4+0];
    inv[1*4+1] = 1.0/pm[1*4+1];
    inv[2*4+3] = 1.0/pm[3*4+2];
    inv[3*4+2] = -1.0;
    inv[3*4+3] = pm[2*4+2]/pm[3*4+2];

    glLoadMatrixd(inv);
};

VARP(crosshairsize, 0, 15, 50);

int dblend = 0;
void damageblend(int n) { dblend += n; };

VARP(hidestats, 0, 1, 1);
VARP(crosshairfx, 0, 1, 1);

void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
{
    readmatrices();
    if(editmode)
    {
        if(cursordepth==1.0f) worldpos = camera1->o;
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        cursorupdate();
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    };

    glDisable(GL_DEPTH_TEST);
    invertperspective();
    glPushMatrix();  
    glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
    glEnable(GL_BLEND);

    if(dblend || underwater)
    {
        glDepthMask(GL_FALSE);
        glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
        glBegin(GL_QUADS);
        if(dblend) glColor3f(0.0f, 0.9f, 0.9f);
        else glColor3f(0.9f, 0.5f, 0.0f);
        glVertex2i(0, 0);
        glVertex2i(VIRTW, 0);
        glVertex2i(VIRTW, VIRTH);
        glVertex2i(0, VIRTH);
        glEnd();
        glDepthMask(GL_TRUE);
        dblend -= min(1, curtime/3);
        if(dblend<0) dblend = 0;
    };

    glEnable(GL_TEXTURE_2D);

    playerent *player = playerincrosshair();
    if(getcurcommand()) rendercommand(20, 1570);
    else if(closeent[0]) draw_text(closeent, 20, 1570);
    else if(player) draw_text(player->name, 20, 1570);

	bool didteamkill = player1->lastteamkill && player1->lastteamkill + 5000 > lastmillis;

    if(!rendermenu())
    {
        bool teammate_in_xhair = player ? (isteam(player->team, player1->team) && player->state!=CS_DEAD) : false;
        if(scoped && player1->gunselect == GUN_SNIPER)
        {
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glEnable(GL_ALPHA_TEST);
            glAlphaFunc(GL_GREATER, 0.9f);
            static Texture *scopetex = NULL;
            if(!scopetex) scopetex = textureload("packages/misc/scope.png");
			glBindTexture(GL_TEXTURE_2D, scopetex->id);
            glBegin(GL_QUADS);
            glColor3ub(255,255,255);
            
            glTexCoord2i(0, 0); glVertex2i(0, 0);
            glTexCoord2i(1, 0); glVertex2i(VIRTW, 0);
            glTexCoord2i(1, 1); glVertex2i(VIRTW, VIRTH);
            glTexCoord2i(0, 1); glVertex2i(0, VIRTH);
			
            glEnd();
            glDisable(GL_ALPHA_TEST);
        }
		else if((player1->gunselect != GUN_SNIPER || teammate_in_xhair) && !player1->reloading && !player1->state==CS_DEAD && !didteamkill)
        {
            glBlendFunc(GL_ONE, GL_ONE);
            static Texture *teammatetex = NULL;
            if(!teammatetex) teammatetex = textureload("packages/misc/teammate.png");
			glBindTexture(GL_TEXTURE_2D, teammate_in_xhair ? teammatetex->id : crosshair->id);
            glBegin(GL_QUADS);
            glColor3ub(255,255,255);
            if(crosshairfx)
            {
                if(teammate_in_xhair) glColor3ub(255, 0, 0);
                else if(player1->gunwait) glColor3ub(128,128,128);
                else if(!m_osok)
                {
                    if(player1->health<=25) glColor3ub(255,0,0);
                    else if(player1->health<=50) glColor3ub(255,128,0);
                };
            };
			float chsize = (float)crosshairsize * (player1->gunselect==GUN_ASSAULT && player1->shots > 3 ? 1.4f : 1.0f) * (teammate_in_xhair ? 2.0f : 1.0f);
            glTexCoord2i(0, 0); glVertex2f(VIRTW/2 - chsize, VIRTH/2 - chsize);
            glTexCoord2i(1, 0); glVertex2f(VIRTW/2 + chsize, VIRTH/2 - chsize);
            glTexCoord2i(1, 1); glVertex2f(VIRTW/2 + chsize, VIRTH/2 + chsize);
            glTexCoord2i(0, 1); glVertex2f(VIRTW/2 - chsize, VIRTH/2 + chsize);
            glEnd();
        };
    };

    glPopMatrix();

    glPushMatrix();    
    glOrtho(0, VIRTW*4/3, VIRTH*4/3, 0, -1, 1);
    renderconsole();

    if(!hidestats)
    {
        glPopMatrix();
        glPushMatrix();
        glOrtho(0, VIRTW*3/2, VIRTH*3/2, 0, -1, 1);
        draw_textf("fps %d", 3200, 2320, curfps);
        draw_textf("lod %d", 3200, 2390, lod_factor());
        draw_textf("wqd %d", 3200, 2460, nquads); 
        draw_textf("wvt %d", 3200, 2530, curvert);
        draw_textf("evt %d", 3200, 2600, xtraverts);
    };
    
    glPopMatrix();

    if(player1->state==CS_ALIVE)
    {
        glPushMatrix();
        glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
        draw_textf("%d",  90, 827, player1->health);
        if(player1->armour) draw_textf("%d", 390, 827, player1->armour);
        if(player1->gunselect!=GUN_KNIFE)
        {
            char gunstats[64];
            if(player1->gunselect!=GUN_GRENADE) sprintf(gunstats,"%i/%i",player1->mag[player1->gunselect],player1->ammo[player1->gunselect]);
            else sprintf(gunstats,"%i",player1->mag[player1->gunselect]);
            draw_text(gunstats, 690, 827);
        };
		glPopMatrix();

		if(didteamkill)
		{
			glPushMatrix();
			glOrtho(0, VIRTW/3, VIRTH/3, 0, -1, 1);
			draw_text("\f3you killed a teammate", VIRTW/3/40, VIRTH/3/2);
			glPopMatrix();
		};

        #define ctf_scl 0.75
        if(m_ctf)
        {
            glPushMatrix();
            glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
            glColor4f(1.0f, 1.0f, 1.0f, 0.2f);            
            if(flaginfos[TEAM_CLA].state == CTFF_INBASE) glDisable(GL_BLEND); else glEnable(GL_BLEND);
            static Texture *flagtex = NULL;
            if(!flagtex) flagtex = textureload("packages/misc/flag_icons.png");
            drawicon(64*ctf_scl, 0, 1940, 1650, flagtex, 1.0f/4.0f);    
            if(flaginfos[TEAM_RVSF].state == CTFF_INBASE) glDisable(GL_BLEND); else glEnable(GL_BLEND);
            drawicon(0, 0, 1820, 1650, flagtex, 1.0f/4.0f); 
            glDisable(GL_BLEND);
            drawicon((float)(team_int(player1->team)*64*ctf_scl), (float)(64*ctf_scl), VIRTW-128-10, 10, flagtex, 1.0/4.0); // shows which team you are
            glPopMatrix();
            
            // big flag icon
            flaginfo &f = flaginfos[team_opposite(team_int(player1->team))];
			if(f.state==CTFF_STOLEN && f.actor == player1 && f.ack)
            {
                glPushMatrix();
                glOrtho(0, VIRTW/2, VIRTH/2, 0, -1, 1);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE);
                glColor4f(1.0f, 1.0f, 1.0f, (sinf(lastmillis / 100.0f) + 1.0f) / 2.0f);
                glEnable(GL_BLEND);
                drawicon((float)(team_opposite(team_int(player1->team))*128*ctf_scl),(float)(128*ctf_scl), 1065, VIRTH/2/3*2, flagtex, 1.0/2.0);
                glPopMatrix();
            };
        };

        glPushMatrix();
        glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
        glDisable(GL_BLEND);
        
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glColor4f(1.0f, 1.0f, 1.0f, 0.2f+(sinf(lastmillis/100.0f)+1.0f)/2.0f);
        
        if(player1->health <= 20 && !m_osok)        
        {
            glEnable(GL_BLEND);
            drawicon(64, 0, 20, 1650);
            glDisable(GL_BLEND);
        }
        else drawicon(64, 0, 20, 1650);
        if(player1->armour) drawicon((float)(128), 0, 620, 1650);
        int g = player1->gunselect;
        int r = 64;
        if(g>2) { g -= 3; r = 128; };
        
        if(!player1->mag[player1->gunselect] && player1->gunselect != GUN_KNIFE && player1->gunselect != GUN_GRENADE)
        {
            glEnable(GL_BLEND);
            drawicon((float)(g*64), (float)r, 1220, 1650);
            glDisable(GL_BLEND);
        }
        else 
        {
            if (player1->gunselect==GUN_GRENADE) drawicon(0, 0, 1220, 1650);
            else drawicon((float)(g*64), (float)r, 1220, 1650);   
        };
        glPopMatrix();
    };

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
};

#define MAXSHOTLINES 100
struct shotline 
{ 
    vec from, to;
    bool inuse;
    int millis;
};
shotline shotlines[MAXSHOTLINES];

void shotlinereset() { loopi(MAXSHOTLINES) shotlines[i].inuse = false; };

void addshotline(dynent *d, vec &from, vec &to)
{
    if(d == player1) return;
    if(rnd(3) != 0) return;
    loopi(MAXSHOTLINES)
    {
        shotline *s = &shotlines[i];
        if(s->inuse) continue;
        int start = 10;
        if(camera1->o.dist(to) <= 10.0f) start = 8;
        else start = 5;
        
        vec unitv;
        float dist = to.dist(from, unitv);
        unitv.div(dist);
        s->inuse = true;
        s->from = unitv;
        s->from.mul(dist/10*start).add(from);
        s->to = unitv;
        s->to.mul(dist/10*-(10-start-2)).add(to);
        s->millis = lastmillis;
        return;
    };
};

void rendershotlines()
{
    int lines = 0;
    loopi(MAXSHOTLINES)
    {
        shotline *s = &shotlines[i];
        if(!s->inuse) continue;
		const int shotline_duration = 75;
        if(lastmillis-s->millis > shotline_duration) { s->inuse = false; continue; }

        if(!lines)
        {
            glPushMatrix();
            glDisable(GL_TEXTURE_2D);
        
            glDepthMask(GL_FALSE);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_SRC_ALPHA);
            glDisable(GL_FOG);
        
            glColor4f(1.0f, 1.0f, 0.7f, 0.5f);
            glBegin(GL_LINES);
        };
        ++lines;

        glVertex3f(s->from.x, s->from.z, s->from.y);
        glVertex3f(s->to.x, s->to.z, s->to.y);
    };
    if(lines)
    {
        glEnd();
        
        glEnable(GL_FOG);
        glDisable(GL_BLEND);
        glDepthMask(GL_TRUE);
        
        glEnable(GL_TEXTURE_2D);
        glPopMatrix();
    };
};

void renderbounceents()
{
    loopv(bounceents)
    {
        bounceent *p = bounceents[i];
		if(!p) continue;
		string model;
		float z = p->o.z;
		
		switch(p->bouncestate)
		{
			case NADE_THROWED:
				s_strcpy(model, "weapons/grenade/static");
				break;
			case GIB:
			default:
            {    
                uint n = (((4*(uint)(size_t)p)+(uint)p->timetolife)%3)+1;
				s_sprintf(model)("misc/gib0%u", n);
				int t = lastmillis-p->millis;
				if(t>p->timetolife-2000)
				{
					t -= p->timetolife-2000;
					z -= t*t/4000000000.0f*t;
				}
				break;
            };
		};
		path(model);
		rendermodel(model, ANIM_MAPMODEL|ANIM_LOOP, 0, 1.1f, p->o.x, z, p->o.y, p->yaw, p->pitch, 10.0f);
    };
};

VARP(gibnum, 0, 6, 1000);
VARP(gibttl, 0, 5000, 15000);
VARP(gibspeed, 1, 5, 20);

void addgib(playerent *d)
{
	if(!d) return;
	playsound(S_GIB, &d->o);
	
	loopi(gibnum)
	{
		bounceent *p = newbounceent();
		p->owner = d;
		p->millis = lastmillis;
		p->timetolife = gibttl+rnd(10)*100;

		p->bouncestate = GIB;

		p->gravity = 20;

		p->o = d->o;
		p->o.z -= d->aboveeye;

		float gibvelangle = (float) rnd(360);
		float speed = (float) gibspeed;
		p->vel.x = sinf(gibvelangle)*speed*rnd(1000)/1000.0f;
		p->vel.y = cosf(gibvelangle)*speed*rnd(1000)/1000.0f;
		p->vel.z = speed*rnd(1000)/1000.0f;
		p->vel.div(10.0f);

		p->yaw = (float)rnd(360);
		p->pitch = (float)rnd(360);
		p->rotspeed = 3.0f;
	};
};

void loadingscreen()
{
    static Texture *logo = NULL;
    if(!logo) logo = textureload("packages/misc/full_logo.png", false);

	glPushMatrix();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glOrtho(0, VIRTW, VIRTH, 0, -1, 1);
	
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);

    glColor3f(1, 1, 1);
	glBindTexture(GL_TEXTURE_2D, logo->id);

	loopi(2)
	{
		glBegin(GL_QUADS);
		glTexCoord2i(0, 0); glVertex2i(0,		0);
		glTexCoord2i(1, 0); glVertex2i(VIRTW,	0);
		glTexCoord2i(1, 1); glVertex2i(VIRTW,	VIRTH);
		glTexCoord2i(0, 1); glVertex2i(0,		VIRTH);
		glEnd();
	
		SDL_GL_SwapBuffers();
	};

	glDisable(GL_TEXTURE_2D);	
	glPopMatrix();
};

