#include<GL/glut.h>
#include<GL/glu.h>
#include<GL/gl.h>

// Initial square position and size
GLfloat x = 0.0f;
GLfloat y = 0.0f;
GLfloat rsize = 40;

// Step size in x and y directions
// (number of pixels to move each time)
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;

// Keep track of windows changing width and height
GLfloat windowWidth;
GLfloat windowHeight;
	
///////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
    {
            
    // Clear black window
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        
    // Use 0 for clear stencil, enable stencil test
    glClearStencil(0.0f);
    glEnable(GL_STENCIL_TEST);

    // Clear color and stencil buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
                
    // All drawing commands fail the stencil test, and are not
    // drawn, but increment the value in the stencil buffer. 
    glStencilFunc(GL_NEVER, 0x0, 0x0);
    glStencilOp(GL_INCR, GL_INCR, GL_INCR);
                    ^
                    |    
        /* lo stencil test fallisce sempre*/

    
    glBegin(GL_TRIANGLES);
    
					// le primitive specificate qui non
					// vengono disegnate perche' lo stencil test
					// fallisce ovunque
                                        // pero' viene aggiornato lo Stencil Buffer

		glVertex2f(-20.0f, 0.0f);  
		glVertex2f(20.0f, 0.0f);  
		glVertex2f(0.0f, 40.0f);  

		glVertex2f(-20.0f,0.0f);
		glVertex2f(-60.0f,-20.0f);
		glVertex2f(-20.0f,-40.0f);

		glVertex2f(-20.0f,-40.0f);
		glVertex2f(0.0f, -80.0f);
		glVertex2f(20.0f, -40.0f);		

		glVertex2f(20.0f, -40.0f);		
		glVertex2f(60.0f, -20.0f);
		glVertex2f(20.0f, 0.0f);
    glEnd();

    glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        
    // Now draw bouncing square
    // (x and y) are modified by a timer function
    glColor3f(1.0f, 1.0f, 1.0f);
    glRectf(x, y, x + rsize, y - rsize);    // Il quadrato viene disegnato solo dove lo
    					    // Stencil Test ha successo	
    glutSwapBuffers();
    }

///////////////////////////////////////////////////////////
// Called by GLUT library when idle (window not being
// resized or moved)
void TimerFunction(int value)
    {
    
    if(x > windowWidth-rsize || x < -windowWidth)
        xstep = -xstep;

   
    if(y > windowHeight || y < -windowHeight + rsize)
        ystep = -ystep;


   if(x > windowWidth-rsize)
        x = windowWidth-rsize-1;

    if(y > windowHeight)
        y = windowHeight-1; 


    x += xstep;
    y += ystep;

   
    glutPostRedisplay();
    glutTimerFunc(33,TimerFunction, 1);
    }


///////////////////////////////////////////////////////////
// Called by GLUT library when the window has chanaged size
void ChangeSize(int w, int h)
    {
    GLfloat aspectRatio;

    // Prevent a divide by zero
    if(h == 0)
        h = 1;
		
 
    glViewport(0, 0, w, h);


    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

 
    aspectRatio = (GLfloat)w / (GLfloat)h;
    if (w <= h) 
        {
        windowWidth = 100;
        windowHeight = 100 / aspectRatio;
        glOrtho (-100.0, 100.0, -windowHeight, windowHeight, -1.0, 1.0);
        }
    else 
        {
        windowWidth = 100 * aspectRatio;
        windowHeight = 100;
        glOrtho (-windowWidth, windowWidth, -100.0, 100.0, -1.0, 1.0);
        }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }
    
    
///////////////////////////////////////////////////////////
// Program entry point
int main(int argc, char* argv[])
	{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL);
	glutInitWindowSize(800,600);
	glutCreateWindow("OpenGL Stencil Test");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
        glutTimerFunc(33, TimerFunction, 1);
	glutMainLoop();

	return 0;
	}
