Where: Room 1.05 in CSSE
and online (active in consultation hour)
You can complete this lab under Linux.  You may need to reboot
	  to choose the operating system. If you use the Linux platform, use
the .cpp and .glsl files supplied under the LINUX_VERSIONS subdirectory.
 
lab1 folder to lab2 - e.g., via: 
cd ~/cits3003/labs-examples
                                 cp -r lab1 lab2
          q3triangleScene.cpp to q1square.cpp and remove the other questions
              from lab2 (keep them in lab1!)
mv q3triangleScene.cpp q1square.cpp
                                 rm q1circle.cpp q2pointsScene.cpp
        
const int NumTriangles = 2;
const int NumVertices  = 3 * NumTriangles;
vec3 points[NumVertices] = {
    vec3(-0.5, -0.5, 0.0), vec3(-0.5, 0.5, 0.0), vec3(0.5, -0.5, 0.0),
    vec3(0.5, 0.5, 0.0),   vec3(0.5, -0.5, 0.0), vec3(-0.5, 0.5, 0.0)
};
             
             Here we use 3D coordinates just to avoid changing it later - for now all z-coordinates are 0.0 (which is
             what OpenGL defaults to anyway if you draw using vec2's).
             You'll need to change the second argument in the call to glVertexAttribPointer from 
             2 to 3.  This is the number of components per vertex - see the 
             OpenGL reference page for this
             function (for other OpenGL functions, see the 
             OpenGL 3.3 Reference Pages on the left of this web page).  
              Use the code above to initialize the triangles and build the program via make and run it.  
              Compare with: 
              
              
points from above):
vec3 colors[NumVertices] = {
    vec3(0.0, 1.0, 0.0) /* Green, but choose any 6 colours */, ..., ...,
    vec3(/* ... */), ..., ...
};
                
         init function from example4.cpp, starting from the comment:
                 // Create a vertex array object
              
         
                  glEnable( GL_DEPTH_TEST ); 
init function and the previous one is that it also sends the 
              color array to the OpenGL buffer.  Then vshader24.glsl uses this 
              color information via the vColor shader input variable.
         
              
              
What colours do you get in between the vertices? Experiment with different colours.
              Instead we can just pass the angle of rotation to the vertex shader, and have it rotate all the vertex
              positions by this angle.  In fact we can just pass the time (since the program started) to the shader and have
              it increase the angle over time.  
         
q1square.cpp to q2sqrotate.cpp.
         vshader24.glsl to vrotate2d.glsl. In the C++ program
	      q2sqrotate.cpp, we will use vrotate2d.glsl and
	      fshader24.glsl together.  In the vertex shader, add
	      the time variable:uniform float time; /* in milliseconds */
              to the top of the file (above main)
         
main function in this vertex shader so that the position is set instead via:
    float angle = 0.001*time;
    gl_Position = vec4(vPosition.x*cos(angle) - vPosition.y*sin(angle),
                       vPosition.x*sin(angle) + vPosition.y*cos(angle),
                       0.0,
                       1.0);
  
                                    
              [Why are there four components in gl_Position?  Because OpenGL actually uses 4D
              homogeneous coordinates - we'll come to this in lectures soon.  For now the last component should
              always be 1.0.] 
             Here the angle is in radians, so the square rotates roughly every 6.28 seconds.  Why sin and
             cos here? Well, basically because that's what sin and cos were 
             invented for! 
 
             cos tells you how much the original (x or y) coordinate affects the same coordinate when rotated. 
             sin tells you how much the original (x or y) coordinate affects the other coordinate when rotated.
             (It's negative in the line for the x coordinate above because the y-axis when rotated clockwise moves towards
              the negative x-direction.) 
See 2D rotation.
InitShader to use your new vertex shader.
         GLint global variable called timeParam to store
              the location of the new shader variable time.  Set this global variable
              in the init function 
              (after the shaders have been loaded and "used") via: 
timeParam = glGetUniformLocation(program, "time");
              [This is a uniform variable which means that it doesn't change during the drawing of a primitive,
               hence no array/buffer is needed unlike vPosition and vColor.]
         
time variable before the call to glDrawArrays via: 
glUniform1f( timeParam, glutGet(GLUT_ELAPSED_TIME) );
              [glUniform1f sets a uniform parameter containing a single float to a value.  Here the value is
               that returned by glutGet(GLUT_ELAPSED_TIME) which is the time (in milliseconds) since
               glutInit was called.  See glutGet
               in the freeglut API (now in the links to the left of this page).
               ]
void idle(void) that just calls glutPostRedisplay().  Then
              add a call to glutIdleFunc in main to set the idle function
              to this function. 
              
              [Calling glutPostRedisplay tells GLUT that the window needs to be redisplayed.
               Here we call it in the idle function because there is constant motion, so we want to redisplay
               whenever GLUT/OpenGL has nothing else to do and is idle.  The actual redisplay will happen at some point after 
               the idle function returns, when GLUT is ready to redraw the window. 
               More generally, if you only require redrawing when a mouse event causes an object to move, or similar, 
               you should only call glutPostRedisplay() when such a change occurs.  Calling it multiple times
               is fine if multiple changes occur before a redraw happens - it just sets a variable that GLUT uses to 
               remember that a redraw is required.]
       
GLUT_DOUBLE to the glutInitDisplayMode call (using bitwise-or, i.e., vertical bar), 
            and replace glFlush()
            with glutSwapBuffers().  This causes double buffering, which prevents flickering.
            Then again, modern graphics hardware often automatically double buffers, so you may not see any difference, including
            when you're using the lab machines.